import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:geolocator/geolocator.dart'; import 'package:rogapp/model/destination.dart'; import 'package:rogapp/pages/index/index_controller.dart'; import 'package:rogapp/utils/const.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:rogapp/pages/destination/destination_controller.dart'; class BottomSheetBase extends StatelessWidget { BottomSheetBase({super.key, required this.destination,this.isAlreadyCheckedIn = false}); final IndexController indexController = Get.find(); final DestinationController destinationController = Get.find(); final bool isAlreadyCheckedIn; // すでにチェックイン済みかどうかのフラグ final Destination destination; // 目的地オブジェクト // そのポイントの写真を取得するメソッド // Image getImage() { String serverUrl = ConstValues.currentServer(); // currentDestinationFeature(destinationそのもの)のphotoデータのチェック // Nouffer のコードでは、indexController.rogMode によって、destination(currentDestinationFeature) かGeoJSONFeature(currentFeature)の違いで処理が分かれていた。 // しかし、現在のコードでは GeoJSONFeature gf = indexController.currentFeature[0]; は使われていない。 // if (indexController.currentDestinationFeature[0].photos! == "") { // 定義されていなければ、empty_image.png を選択 return const Image(image: AssetImage('assets/images/empty_image.png')); } else { String photo = indexController.currentDestinationFeature[0].photos!; if (photo.contains('http')) { // photo にhttpの文字が含まれていれば、ネットから拾ってくる。エラーならempty_image.pngを表示。 return Image( image: NetworkImage( indexController.currentDestinationFeature[0].photos!, ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } else { // photo にhttpの文字が含まれていなければ、指定サーバー($serverUrl/media/compressed/*)から拾ってくる。エラーならempty_image.pngを表示。 return Image( image: NetworkImage( '$serverUrl/media/compressed/${indexController.currentDestinationFeature[0].photos!}', ), errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return Image.asset("assets/images/empty_image.png"); }, ); } } } // URLを開くためのメソッドです。 // url_launcherパッケージを使用して、指定されたURLを開きます。 // void _launchURL(url) async { if (!await launchUrl(url)) throw 'Could not launch $url'; } // 指定されたlocationidが目的地リストに含まれているかどうかを確認するメソッドです。 // destinationController.destinationsリストを走査し、locationidが一致する目的地があるかどうかを返します。 // bool isInDestination(String locationid) { int lid = int.parse(locationid); if (destinationController.destinations .where((element) => element.location_id == lid) .isNotEmpty) { return true; } else { return false; } } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Column( children: buildWidgets(context), ), ); } // このメソッドはListを返します。 List buildWidgets(BuildContext context) { return [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ MaterialButton( onPressed: () { Get.back(); }, color: Colors.blue, textColor: Colors.white, padding: const EdgeInsets.all(16), shape: const CircleBorder(), child: const Icon(Icons.arrow_back_ios, size: 14), ), Expanded( child: Container( alignment: Alignment.center, child: Obx(() => Text("${destination.sub_loc_id} : ${destination.name}", style: const TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold))), ), ), ], ), ), Row( children: [Expanded(child: SizedBox(height: 260.0, child: Obx(() => getImage())))], ), Obx(() => Padding( padding: const EdgeInsets.all(8.0), child: getDetails(context), )), const SizedBox(height: 60.0), ]; } Widget getDetails(BuildContext context) { return Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.roundabout_left), const SizedBox( width: 8.0, ), destination.address != null && destination.address!.isNotEmpty ? getDetailsItem( context, "address".tr, destination.address ?? '', ) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.phone), const SizedBox( width: 8.0, ), destination.phone != null && destination.phone!.isNotEmpty ? getDetailsItem( context, "telephone".tr, destination.phone ?? '', ) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.email), const SizedBox( width: 8.0, ), destination.email != null && destination.email!.isNotEmpty ? getDetailsItem( context, "email".tr, destination.email ?? '', ) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const Icon(Icons.language), const SizedBox( width: 8.0, ), destination.webcontents != null && destination.webcontents!.isNotEmpty ? getDetailsItem( context, "web".tr, destination.webcontents ?? '', isUrl: true, ) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ const SizedBox( width: 8.0, ), indexController.currentFeature[0] .properties!["remark"] != null && (indexController.currentFeature[0] .properties!["remark"] as String) .isNotEmpty ? getDetailsItem( context, "remarks".tr, indexController.currentFeature[0] .properties!["remark"] ?? '', isUrl: false) : const SizedBox( width: 0.0, height: 0, ), ], ), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.onPrimaryContainer), onPressed: () async { // print( // "dist to start ${destinationController.distanceToStart()}"); Get.back(); //print("---- go to ----"); // GeoJSONMultiPoint mp = indexController // .currentFeature[0] as GeoJSONMultiPoint; Position position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.bestForNavigation, forceAndroidLocationManager: true); //print("------- position -------- $position"); Destination ds = Destination( lat: position.latitude, lon: position.longitude); Destination tp = Destination( lat: destination.lat, lon: destination.lon); destinationController .destinationMatrixFromCurrentPoint([ds, tp]); // TODO: Implement "ここへ行く" functionality }, child: Text( "ルート", style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, ), ), ), const SizedBox( width: 10, ), ], ), ], ); } Widget getDetailsItem(BuildContext context, String label, String text, {bool isUrl = false}) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(label), const SizedBox( width: 10.0, ), InkWell( onTap: () { if (isUrl) { _launchURL(destination.webcontents); } }, child: SizedBox( width: MediaQuery.of(context).size.width - (MediaQuery.of(context).size.width * 0.35), child: Text( text, textAlign: TextAlign.justify, style: TextStyle( color: isUrl ? Colors.blue : Colors.black, ), ), ), ), ], ); } }