release 4.8.9
This commit is contained in:
@ -1,9 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert'; // この行を追加または確認
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:rogapp/model/destination.dart';
|
||||
import 'package:rogapp/pages/destination/destination_controller.dart';
|
||||
import 'package:rogapp/pages/index/index_controller.dart';
|
||||
@ -493,7 +496,10 @@ class CameraPage extends StatelessWidget {
|
||||
if (buyPointPhoto == true) {
|
||||
// buyPointPhotoがtrueの場合は、BuyPointCameraウィジェットを返します。
|
||||
//print("--- buy point camera ${destination.toString()}");
|
||||
return BuyPointCamera(destination: destination);
|
||||
//return BuyPointCamera(destination: destination);
|
||||
|
||||
return SwitchableBuyPointCamera(destination: destination);
|
||||
|
||||
//}else if(destination.use_qr_code){
|
||||
// return QRCodeScannerPage(destination: destination);
|
||||
} else if (destinationController.isInRog.value) {
|
||||
@ -617,105 +623,189 @@ class StartRogaining extends StatelessWidget {
|
||||
// 完了ボタンをタップすると、購入ポイントの処理が行われます。
|
||||
// 購入なしボタンをタップすると、購入ポイントがキャンセルされます。
|
||||
//
|
||||
class SwitchableBuyPointCamera extends StatefulWidget {
|
||||
final Destination destination;
|
||||
|
||||
const SwitchableBuyPointCamera({Key? key, required this.destination}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SwitchableBuyPointCameraState createState() => _SwitchableBuyPointCameraState();
|
||||
}
|
||||
|
||||
class _SwitchableBuyPointCameraState extends State<SwitchableBuyPointCamera> {
|
||||
bool isQRMode = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
final qrViewWidth = screenWidth * 2 / 3;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: Text("${widget.destination.sub_loc_id} : ${widget.destination.name}"),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
if (isQRMode)
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: screenHeight * 0.1),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: qrViewWidth,
|
||||
height: qrViewWidth,
|
||||
child: BuyPointCamera_QR(destination: widget.destination),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Text(
|
||||
"岐阜ロゲQRコードにかざしてください。",
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
else
|
||||
Positioned.fill(
|
||||
child: BuyPointCamera(destination: widget.destination),
|
||||
),
|
||||
Positioned(
|
||||
right: 16,
|
||||
bottom: 16,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(isQRMode ? "カメラへ" : "QRへ"),
|
||||
Switch(
|
||||
value: isQRMode,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
isQRMode = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BuyPointCamera extends StatelessWidget {
|
||||
BuyPointCamera({Key? key, required this.destination}) : super(key: key);
|
||||
|
||||
Destination destination;
|
||||
|
||||
DestinationController destinationController =
|
||||
Get.find<DestinationController>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: Text(
|
||||
"${destination.sub_loc_id} : ${destination.name}",
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Obx(
|
||||
() => Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: 370,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
// 要修正:getReceiptImage関数の戻り値がnullの場合のエラーハンドリングが不十分です。適切なデフォルト画像を表示するなどの処理を追加してください。
|
||||
//
|
||||
image: getReceiptImage(), fit: BoxFit.cover)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(getTagText(true, destination.tags)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Wrap(
|
||||
spacing: 16.0,
|
||||
runSpacing: 8.0,
|
||||
children: [
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: () {
|
||||
destinationController.openCamera(context, destination);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
padding: const EdgeInsets.all(20),
|
||||
backgroundColor: destinationController.photos.isEmpty
|
||||
? Colors.red
|
||||
: Colors.grey[300],
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Obx(
|
||||
() =>
|
||||
Container(
|
||||
width: MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.width,
|
||||
height: 370,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
// 要修正:getReceiptImage関数の戻り値がnullの場合のエラーハンドリングが不十分です。適切なデフォルト画像を表示するなどの処理を追加してください。
|
||||
//
|
||||
image: getReceiptImage(), fit: BoxFit.cover)),
|
||||
),
|
||||
child: destinationController.photos.isEmpty
|
||||
? const Text("撮影",
|
||||
style: TextStyle(color: Colors.white))
|
||||
: const Text("再撮影",
|
||||
style: TextStyle(color: Colors.black)),
|
||||
)),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
await destinationController.cancelBuyPoint(destination);
|
||||
Navigator.of(Get.context!).pop();
|
||||
destinationController.rogainingCounted.value = true;
|
||||
destinationController.skipGps = false;
|
||||
destinationController.isPhotoShoot.value = false;
|
||||
},
|
||||
child: const Text("買い物なし")),
|
||||
Obx(() => destinationController.photos.isNotEmpty
|
||||
? ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red),
|
||||
onPressed: () async {
|
||||
await destinationController.makeBuyPoint(
|
||||
destination,
|
||||
destinationController.photos[0].path);
|
||||
Get.back();
|
||||
destinationController.rogainingCounted.value = true;
|
||||
destinationController.skipGps = false;
|
||||
destinationController.isPhotoShoot.value = false;
|
||||
Get.snackbar("お買い物加点を行いました",
|
||||
"${destination.sub_loc_id} : ${destination.name}",
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white);
|
||||
},
|
||||
child: const Text("完了",
|
||||
style: TextStyle(color: Colors.white)))
|
||||
: Container())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(getTagText(true, destination.tags)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Wrap(
|
||||
spacing: 16.0,
|
||||
runSpacing: 8.0,
|
||||
children: [
|
||||
Obx(() =>
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
destinationController.openCamera(context, destination);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
padding: const EdgeInsets.all(20),
|
||||
backgroundColor: destinationController.photos.isEmpty
|
||||
? Colors.red
|
||||
: Colors.grey[300],
|
||||
),
|
||||
child: destinationController.photos.isEmpty
|
||||
? const Text("撮影",
|
||||
style: TextStyle(color: Colors.white))
|
||||
: const Text("再撮影",
|
||||
style: TextStyle(color: Colors.black)),
|
||||
)),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
await destinationController.cancelBuyPoint(destination);
|
||||
Navigator.of(Get.context!).pop();
|
||||
destinationController.rogainingCounted.value = true;
|
||||
destinationController.skipGps = false;
|
||||
destinationController.isPhotoShoot.value = false;
|
||||
},
|
||||
child: const Text("買い物なし")),
|
||||
Obx(() =>
|
||||
destinationController.photos.isNotEmpty
|
||||
? ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red),
|
||||
onPressed: () async {
|
||||
await destinationController.makeBuyPoint(
|
||||
destination,
|
||||
destinationController.photos[0].path);
|
||||
Get.back();
|
||||
destinationController.rogainingCounted.value = true;
|
||||
destinationController.skipGps = false;
|
||||
destinationController.isPhotoShoot.value = false;
|
||||
Get.snackbar("お買い物加点を行いました",
|
||||
"${destination.sub_loc_id} : ${destination.name}",
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white);
|
||||
},
|
||||
child: const Text("完了",
|
||||
style: TextStyle(color: Colors.white)))
|
||||
: Container())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -743,28 +833,9 @@ class _BuyPointCamera_QRState extends State<BuyPointCamera_QR> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: Text("${widget.destination.sub_loc_id} : ${widget.destination.name}"),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: QRView(
|
||||
key: qrKey,
|
||||
onQRViewCreated: _onQRViewCreated,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Center(
|
||||
child: Text('QRコードをスキャンしてください'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return QRView(
|
||||
key: qrKey,
|
||||
onQRViewCreated: _onQRViewCreated,
|
||||
);
|
||||
}
|
||||
|
||||
@ -773,11 +844,39 @@ class _BuyPointCamera_QRState extends State<BuyPointCamera_QR> {
|
||||
controller.scannedDataStream.listen((scanData) {
|
||||
if (!isQRScanned && scanData.code != null && scanData.code!.startsWith('https://rogaining.sumasen.net/api/activate_buy_point/')) {
|
||||
isQRScanned = true;
|
||||
_activateBuyPoint(scanData.code!);
|
||||
_processBuyPoint();
|
||||
//_activateBuyPoint(scanData.code!);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> getImageFilePathFromAssets(String assetPath) async {
|
||||
final byteData = await rootBundle.load(assetPath);
|
||||
final buffer = byteData.buffer;
|
||||
Directory tempDir = await getTemporaryDirectory();
|
||||
String tempPath = tempDir.path;
|
||||
var filePath = '$tempPath/temp_qr_receipt.png';
|
||||
return (await File(filePath).writeAsBytes(
|
||||
buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)
|
||||
)).path;
|
||||
}
|
||||
|
||||
|
||||
void _processBuyPoint() async {
|
||||
// アセットの画像をテンポラリファイルにコピー
|
||||
String predefinedImagePath = await getImageFilePathFromAssets('assets/images/QR_certificate.png');
|
||||
|
||||
try {
|
||||
await destinationController.makeBuyPoint(widget.destination, predefinedImagePath);
|
||||
Get.snackbar('成功', 'お買い物ポイントが有効化されました');
|
||||
Navigator.of(context).pop();
|
||||
} catch (e) {
|
||||
Get.snackbar('エラー', 'お買い物ポイントの有効化に失敗しました');
|
||||
} finally {
|
||||
isQRScanned = false;
|
||||
}
|
||||
}
|
||||
|
||||
void _activateBuyPoint(String qrCode) async {
|
||||
final IndexController indexController = Get.find<IndexController>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user