display more landmark information #21
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import 'package:anyway/structs/landmark.dart';
|
import 'package:anyway/structs/landmark.dart';
|
||||||
|
|
||||||
|
|
||||||
class LandmarkCard extends StatefulWidget {
|
class LandmarkCard extends StatefulWidget {
|
||||||
final Landmark landmark;
|
final Landmark landmark;
|
||||||
|
|
||||||
@ -18,6 +18,10 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ThemeData theme = Theme.of(context);
|
ThemeData theme = Theme.of(context);
|
||||||
|
ButtonStyle buttonStyle = TextButton.styleFrom(
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
fixedSize: Size.fromHeight(20)
|
||||||
|
);
|
||||||
return Container(
|
return Container(
|
||||||
height: 160,
|
height: 160,
|
||||||
child: Card(
|
child: Card(
|
||||||
@ -62,15 +66,62 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
if (widget.landmark.nameEN != null)
|
||||||
children: [
|
Row(
|
||||||
Flexible(
|
children: [
|
||||||
child: Text(
|
Flexible(
|
||||||
"${widget.landmark.name} (${widget.landmark.type.name})",
|
child: Text(
|
||||||
style: const TextStyle(fontSize: 14),
|
widget.landmark.nameEN!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SingleChildScrollView(
|
||||||
|
// allows the buttons to be scrolled
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
// show the type, the website, and the wikipedia link as buttons/labels in a row
|
||||||
|
children: [
|
||||||
|
TextButton.icon(
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: () {},
|
||||||
|
icon: widget.landmark.type.icon,
|
||||||
|
label: Text(widget.landmark.type.name),
|
||||||
),
|
),
|
||||||
)
|
if (widget.landmark.duration != null && widget.landmark.duration!.inMinutes > 0)
|
||||||
]
|
TextButton.icon(
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(Icons.hourglass_bottom),
|
||||||
|
label: Text('${widget.landmark.duration!.inMinutes} minutes'),
|
||||||
|
),
|
||||||
|
if (widget.landmark.websiteURL != null)
|
||||||
|
TextButton.icon(
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: () async {
|
||||||
|
// open a browser with the website link
|
||||||
|
await launchUrl(Uri.parse(widget.landmark.websiteURL!));
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.link),
|
||||||
|
label: Text('Website'),
|
||||||
|
),
|
||||||
|
if (widget.landmark.wikipediaURL != null)
|
||||||
|
TextButton.icon(
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: () async {
|
||||||
|
// open a browser with the wikipedia link
|
||||||
|
await launchUrl(Uri.parse(widget.landmark.wikipediaURL!));
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.book),
|
||||||
|
label: Text('Wikipedia'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
const LandmarkType sightseeing = LandmarkType(name: 'sightseeing');
|
LandmarkType sightseeing = LandmarkType(name: 'sightseeing');
|
||||||
const LandmarkType nature = LandmarkType(name: 'nature');
|
LandmarkType nature = LandmarkType(name: 'nature');
|
||||||
const LandmarkType shopping = LandmarkType(name: 'shopping');
|
LandmarkType shopping = LandmarkType(name: 'shopping');
|
||||||
// const LandmarkType museum = LandmarkType(name: 'Museum');
|
// LandmarkType museum = LandmarkType(name: 'Museum');
|
||||||
// const LandmarkType restaurant = LandmarkType(name: 'Restaurant');
|
// LandmarkType restaurant = LandmarkType(name: 'Restaurant');
|
||||||
const LandmarkType start = LandmarkType(name: 'start');
|
LandmarkType start = LandmarkType(name: 'start');
|
||||||
const LandmarkType finish = LandmarkType(name: 'finish');
|
LandmarkType finish = LandmarkType(name: 'finish');
|
||||||
|
|
||||||
|
|
||||||
final class Landmark extends LinkedListEntry<Landmark>{
|
final class Landmark extends LinkedListEntry<Landmark>{
|
||||||
@ -21,6 +22,9 @@ final class Landmark extends LinkedListEntry<Landmark>{
|
|||||||
final bool? isSecondary;
|
final bool? isSecondary;
|
||||||
|
|
||||||
// description to be shown in the overview
|
// description to be shown in the overview
|
||||||
|
final String? nameEN;
|
||||||
|
final String? websiteURL;
|
||||||
|
final String? wikipediaURL;
|
||||||
final String? imageURL;
|
final String? imageURL;
|
||||||
final String? description;
|
final String? description;
|
||||||
final Duration? duration;
|
final Duration? duration;
|
||||||
@ -38,6 +42,9 @@ final class Landmark extends LinkedListEntry<Landmark>{
|
|||||||
required this.type,
|
required this.type,
|
||||||
this.isSecondary,
|
this.isSecondary,
|
||||||
|
|
||||||
|
this.nameEN,
|
||||||
|
this.websiteURL,
|
||||||
|
this.wikipediaURL,
|
||||||
this.imageURL,
|
this.imageURL,
|
||||||
this.description,
|
this.description,
|
||||||
this.duration,
|
this.duration,
|
||||||
@ -61,15 +68,30 @@ final class Landmark extends LinkedListEntry<Landmark>{
|
|||||||
// parse the rest separately, they could be missing
|
// parse the rest separately, they could be missing
|
||||||
LandmarkType typeFixed = LandmarkType(name: type);
|
LandmarkType typeFixed = LandmarkType(name: type);
|
||||||
final isSecondary = json['is_secondary'] as bool?;
|
final isSecondary = json['is_secondary'] as bool?;
|
||||||
|
final nameEN = json['name_en'] as String?;
|
||||||
|
final websiteURL = json['website_url'] as String?;
|
||||||
|
final wikipediaURL = json['wikipedia_url'] as String?;
|
||||||
final imageURL = json['image_url'] as String?;
|
final imageURL = json['image_url'] as String?;
|
||||||
final description = json['description'] as String?;
|
final description = json['description'] as String?;
|
||||||
var duration = Duration(minutes: json['duration'] ?? 0) as Duration?;
|
var duration = Duration(minutes: json['duration'] ?? 0) as Duration?;
|
||||||
// if (duration == const Duration()) {duration = null;};
|
|
||||||
final visited = json['visited'] as bool?;
|
final visited = json['visited'] as bool?;
|
||||||
var tripTime = Duration(minutes: json['time_to_reach_next'] ?? 0) as Duration?;
|
var tripTime = Duration(minutes: json['time_to_reach_next'] ?? 0) as Duration?;
|
||||||
|
|
||||||
return Landmark(
|
return Landmark(
|
||||||
uuid: uuid, name: name, location: locationFixed, type: typeFixed, isSecondary: isSecondary, imageURL: imageURL, description: description, duration: duration, visited: visited, tripTime: tripTime);
|
uuid: uuid,
|
||||||
|
name: name,
|
||||||
|
location: locationFixed,
|
||||||
|
type: typeFixed,
|
||||||
|
isSecondary: isSecondary,
|
||||||
|
nameEN: nameEN,
|
||||||
|
websiteURL: websiteURL,
|
||||||
|
wikipediaURL: wikipediaURL,
|
||||||
|
imageURL: imageURL,
|
||||||
|
description: description,
|
||||||
|
duration: duration,
|
||||||
|
visited: visited,
|
||||||
|
tripTime: tripTime
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw FormatException('Invalid JSON: $json');
|
throw FormatException('Invalid JSON: $json');
|
||||||
}
|
}
|
||||||
@ -88,6 +110,9 @@ final class Landmark extends LinkedListEntry<Landmark>{
|
|||||||
'location': location,
|
'location': location,
|
||||||
'type': type.name,
|
'type': type.name,
|
||||||
'is_secondary': isSecondary,
|
'is_secondary': isSecondary,
|
||||||
|
'name_en': nameEN,
|
||||||
|
'website_url': websiteURL,
|
||||||
|
'wikipedia_url': wikipediaURL,
|
||||||
'image_url': imageURL,
|
'image_url': imageURL,
|
||||||
'description': description,
|
'description': description,
|
||||||
'duration': duration?.inMinutes,
|
'duration': duration?.inMinutes,
|
||||||
@ -100,13 +125,29 @@ final class Landmark extends LinkedListEntry<Landmark>{
|
|||||||
class LandmarkType {
|
class LandmarkType {
|
||||||
final String name;
|
final String name;
|
||||||
// final String description;
|
// final String description;
|
||||||
// final Icon icon;
|
Icon icon;
|
||||||
|
|
||||||
const LandmarkType({
|
LandmarkType({required this.name, this.icon = const Icon(Icons.location_on)}) {
|
||||||
required this.name,
|
switch (name) {
|
||||||
// required this.description,
|
case 'sightseeing':
|
||||||
// required this.icon,
|
icon = Icon(Icons.church);
|
||||||
});
|
break;
|
||||||
|
case 'nature':
|
||||||
|
icon = Icon(Icons.eco);
|
||||||
|
break;
|
||||||
|
case 'shopping':
|
||||||
|
icon = Icon(Icons.shopping_cart);
|
||||||
|
break;
|
||||||
|
case 'start':
|
||||||
|
icon = Icon(Icons.play_arrow);
|
||||||
|
break;
|
||||||
|
case 'finish':
|
||||||
|
icon = Icon(Icons.flag);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
icon = Icon(Icons.location_on);
|
||||||
|
}
|
||||||
|
}
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
if (other is LandmarkType) {
|
if (other is LandmarkType) {
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
@ -8,9 +8,11 @@ import Foundation
|
|||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite
|
import sqflite
|
||||||
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
}
|
}
|
||||||
|
@ -661,6 +661,70 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.2"
|
||||||
|
url_launcher:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: url_launcher
|
||||||
|
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.0"
|
||||||
|
url_launcher_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_android
|
||||||
|
sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.10"
|
||||||
|
url_launcher_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_ios
|
||||||
|
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.1"
|
||||||
|
url_launcher_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_linux
|
||||||
|
sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.0"
|
||||||
|
url_launcher_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_macos
|
||||||
|
sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.0"
|
||||||
|
url_launcher_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_platform_interface
|
||||||
|
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
url_launcher_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_web
|
||||||
|
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.3"
|
||||||
|
url_launcher_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_windows
|
||||||
|
sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -705,10 +769,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
|
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.4"
|
version: "14.2.5"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -742,5 +806,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "6.5.0"
|
version: "6.5.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.4.0 <4.0.0"
|
dart: ">=3.5.0 <4.0.0"
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.24.0"
|
||||||
|
@ -47,6 +47,7 @@ dependencies:
|
|||||||
auto_size_text: ^3.0.0
|
auto_size_text: ^3.0.0
|
||||||
map_launcher: ^3.3.1
|
map_launcher: ^3.3.1
|
||||||
flutter_svg: ^2.0.10+1
|
flutter_svg: ^2.0.10+1
|
||||||
|
url_launcher: ^6.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
Loading…
x
Reference in New Issue
Block a user