20240903 pre release
@ -1,13 +1,58 @@
|
|||||||
import Flutter
|
import Flutter
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import CoreMotion
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
private let motionManager = CMMotionManager()
|
||||||
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
//GeneratedPluginRegistrant.register(with: self)
|
||||||
|
//return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||||
|
let motionChannel = FlutterMethodChannel(name: "com.yourcompany.app/motion",
|
||||||
|
binaryMessenger: controller.binaryMessenger)
|
||||||
|
motionChannel.setMethodCallHandler({
|
||||||
|
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
switch call.method {
|
||||||
|
case "startMotionUpdates":
|
||||||
|
self.startMotionUpdates(result: result)
|
||||||
|
case "stopMotionUpdates":
|
||||||
|
self.stopMotionUpdates(result: result)
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func startMotionUpdates(result: @escaping FlutterResult) {
|
||||||
|
if motionManager.isDeviceMotionAvailable {
|
||||||
|
motionManager.deviceMotionUpdateInterval = 0.1
|
||||||
|
motionManager.startDeviceMotionUpdates(to: .main) { (motion, error) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// ここでUIの更新や状態の取得を行う
|
||||||
|
let appState = UIApplication.shared.applicationState
|
||||||
|
// 必要な処理を行う
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result(nil)
|
||||||
|
} else {
|
||||||
|
result(FlutterError(code: "UNAVAILABLE",
|
||||||
|
message: "Device motion is not available.",
|
||||||
|
details: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopMotionUpdates(result: @escaping FlutterResult) {
|
||||||
|
motionManager.stopDeviceMotionUpdates()
|
||||||
|
result(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
"filename" : "Icon-App-20x20@2x 1.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
"scale" : "2x",
|
||||||
"scale" : "2x"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@3x.png",
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
"scale" : "3x"
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"filename" : "Icon-App-29x29@1x 1.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
"scale" : "1x",
|
||||||
"scale" : "1x"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"filename" : "Icon-App-29x29@2x 1.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
"scale" : "2x",
|
||||||
"scale" : "2x"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@3x.png",
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
"scale" : "3x"
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
"filename" : "Icon-App-40x40@2x 1.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
"scale" : "2x",
|
||||||
"scale" : "2x"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-40x40@3x.png",
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
"scale" : "3x"
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-60x60@2x.png",
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
"filename" : "Icon-App-60x60@3x.png",
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
"scale" : "3x"
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@1x.png",
|
"filename" : "Icon-App-20x20@1x.png",
|
||||||
"scale" : "1x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
"scale" : "2x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
"scale" : "1x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
"scale" : "2x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@1x.png",
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
"scale" : "1x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
"scale" : "2x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@1x.png",
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
"scale" : "1x"
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@2x.png",
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "83.5x83.5",
|
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
"scale" : "2x",
|
||||||
"scale" : "2x"
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "83.5x83.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "1024x1024",
|
|
||||||
"idiom" : "ios-marketing",
|
|
||||||
"filename" : "Icon-App-1024x1024@1x.png",
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
"scale" : "1x"
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 14 KiB |
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x 2.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "LaunchImage.png",
|
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x 1.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "LaunchImage@2x.png",
|
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "LaunchImage@3x.png",
|
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/Icon-App-1024x1024@1x 1.png
vendored
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/Icon-App-1024x1024@1x 2.png
vendored
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/Icon-App-1024x1024@1x.png
vendored
Normal file
|
After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B |
@ -1,8 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
@ -14,24 +16,37 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="岐阜ナビ" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WPs-nj-CIV">
|
||||||
|
<rect key="frame" x="46" y="123" width="314" height="59"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="32"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="NPO 岐阜aiネットワーク" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TM1-SD-6RA">
|
||||||
|
<rect key="frame" x="46" y="722" width="314" height="41"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="hCH-Iu-4S2">
|
||||||
|
<rect key="frame" x="83" y="314" width="240" height="224"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="53" y="375"/>
|
<point key="canvasLocation" x="80.152671755725194" y="264.08450704225356"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="LaunchImage" width="168" height="185"/>
|
<image name="LaunchImage" width="341.33334350585938" height="341.33334350585938"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
65
ios_setup/Info.plist
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>岐阜ナビ</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>岐阜ナビ</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>岐阜ナビはチェックポイントで撮影した写真を写真ライブラリに保存し、通過記録を保持し、競技結果として提出することができます。</string>
|
||||||
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
|
<string>岐阜ナビはアプリが閉じられているときでも位置情報へのアクセスが必要です。これにより、走行履歴の記録ができ、レビュー時の参考にすることができます。</string>
|
||||||
|
<key>NSLocationAlwaysUsageDescription</key>
|
||||||
|
<string>このアプリではバックグラウンドで位置情報にアクセスします。</string>
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string>このアプリはチェックポイントへのチェックインや走行履歴を記録するために、位置情報にアクセスします。</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>このアプリではカメラは使用しますが、マイクの使用は当面行いません。</string>
|
||||||
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
|
<string>撮影した写真はデバイスのアルバムに保存されます。これにより、不具合時の通過記録を安全に担保することができます。</string>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>撮影した写真はデバイスのアルバムに保存されます。これにより、不具合時の通過記録を安全に担保することができます。</string>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIMainStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
56
ios_setup/Runner/AppDelegate.swift
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import UIKit
|
||||||
|
import Flutter
|
||||||
|
import CoreMotion
|
||||||
|
|
||||||
|
@UIApplicationMain
|
||||||
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
private let motionManager = CMMotionManager()
|
||||||
|
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
) -> Bool {
|
||||||
|
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||||
|
let motionChannel = FlutterMethodChannel(name: "com.yourcompany.app/motion",
|
||||||
|
binaryMessenger: controller.binaryMessenger)
|
||||||
|
motionChannel.setMethodCallHandler({
|
||||||
|
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
switch call.method {
|
||||||
|
case "startMotionUpdates":
|
||||||
|
self.startMotionUpdates(result: result)
|
||||||
|
case "stopMotionUpdates":
|
||||||
|
self.stopMotionUpdates(result: result)
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startMotionUpdates(result: @escaping FlutterResult) {
|
||||||
|
if motionManager.isDeviceMotionAvailable {
|
||||||
|
motionManager.deviceMotionUpdateInterval = 0.1
|
||||||
|
motionManager.startDeviceMotionUpdates(to: .main) { (motion, error) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// ここでUIの更新や状態の取得を行う
|
||||||
|
let appState = UIApplication.shared.applicationState
|
||||||
|
// 必要な処理を行う
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result(nil)
|
||||||
|
} else {
|
||||||
|
result(FlutterError(code: "UNAVAILABLE",
|
||||||
|
message: "Device motion is not available.",
|
||||||
|
details: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopMotionUpdates(result: @escaping FlutterResult) {
|
||||||
|
motionManager.stopDeviceMotionUpdates()
|
||||||
|
result(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
30
ios_setup/services/main.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:your_app/services/motion_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
// アプリの起動時にモーション更新を開始
|
||||||
|
await MotionService.startMotionUpdates();
|
||||||
|
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
// ... アプリの設定
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// アプリケーションの状態が変わったときにモーション更新を停止/再開する
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
if (state == AppLifecycleState.paused) {
|
||||||
|
MotionService.stopMotionUpdates();
|
||||||
|
} else if (state == AppLifecycleState.resumed) {
|
||||||
|
MotionService.startMotionUpdates();
|
||||||
|
}
|
||||||
|
}
|
||||||
21
ios_setup/services/motion_service.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class MotionService {
|
||||||
|
static const MethodChannel _channel = MethodChannel('com.yourcompany.app/motion');
|
||||||
|
|
||||||
|
static Future<void> startMotionUpdates() async {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('startMotionUpdates');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print("Failed to start motion updates: '${e.message}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> stopMotionUpdates() async {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('stopMotionUpdates');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print("Failed to stop motion updates: '${e.message}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
lib/main.dart
@ -43,6 +43,8 @@ import 'package:gifunavi/provider/cached_tile_provider.dart';
|
|||||||
|
|
||||||
import 'package:timezone/timezone.dart' as tz;
|
import 'package:timezone/timezone.dart' as tz;
|
||||||
|
|
||||||
|
import 'package:gifunavi/services/motion_service.dart';
|
||||||
|
|
||||||
Map<String, dynamic> deviceInfo = {};
|
Map<String, dynamic> deviceInfo = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -70,7 +72,9 @@ Future<void> saveGameState() async {
|
|||||||
if(indexController.currentUser[0]["user"]["event_date"]!=null) {
|
if(indexController.currentUser[0]["user"]["event_date"]!=null) {
|
||||||
final date = indexController.currentUser[0]["user"]["event_date"];
|
final date = indexController.currentUser[0]["user"]["event_date"];
|
||||||
pref.setString('eventDate', date.toIso8601String());
|
pref.setString('eventDate', date.toIso8601String());
|
||||||
|
|
||||||
debugPrint("Saved date is ${date} => ${date.toIso8601String()}");
|
debugPrint("Saved date is ${date} => ${date.toIso8601String()}");
|
||||||
|
|
||||||
pref.setString('eventCode', indexController.currentUser[0]["user"]["event_code"]);
|
pref.setString('eventCode', indexController.currentUser[0]["user"]["event_code"]);
|
||||||
pref.setString('teamName', indexController.currentUser[0]["user"]["team_name"]);
|
pref.setString('teamName', indexController.currentUser[0]["user"]["team_name"]);
|
||||||
pref.setString('group', indexController.currentUser[0]["user"]["group"]);
|
pref.setString('group', indexController.currentUser[0]["user"]["group"]);
|
||||||
@ -197,6 +201,11 @@ void _showEventSelectionWarning() {
|
|||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
// アプリの起動時にモーション更新を開始
|
||||||
|
await MotionService.startMotionUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
final IndexController _indexController;
|
final IndexController _indexController;
|
||||||
|
|
||||||
FlutterError.onError = (FlutterErrorDetails details) {
|
FlutterError.onError = (FlutterErrorDetails details) {
|
||||||
@ -207,20 +216,7 @@ void main() async {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//await Get.putAsync(() => ApiService().init());
|
|
||||||
await _initApiService();
|
|
||||||
debugPrint("1: start ApiService");
|
|
||||||
|
|
||||||
// すべてのコントローラーとサービスを非同期で初期化
|
|
||||||
Get.lazyPut(() => IndexController(apiService: Get.find<ApiService>()));
|
|
||||||
debugPrint("2: start IndexController");
|
|
||||||
|
|
||||||
|
|
||||||
// その他のコントローラーを遅延初期化
|
|
||||||
Get.lazyPut(() => SettingsController());
|
|
||||||
debugPrint("2: start SettingsController");
|
|
||||||
Get.lazyPut(() => DestinationController());
|
|
||||||
debugPrint("3: start DestinationController");
|
|
||||||
|
|
||||||
await initServices();
|
await initServices();
|
||||||
|
|
||||||
@ -237,12 +233,37 @@ void main() async {
|
|||||||
Future<void> initServices() async {
|
Future<void> initServices() async {
|
||||||
print('Starting services ...');
|
print('Starting services ...');
|
||||||
try {
|
try {
|
||||||
|
//await Get.putAsync(() => ApiService().init());
|
||||||
|
await _initApiService();
|
||||||
|
debugPrint("1: start ApiService");
|
||||||
|
|
||||||
|
// コントローラーを初期化
|
||||||
|
Get.put(IndexController(apiService: Get.find<ApiService>()), permanent: true);
|
||||||
|
Get.put(SettingsController(), permanent: true);
|
||||||
|
Get.put(DestinationController(), permanent: true);
|
||||||
|
Get.put(LocationController(), permanent: true);
|
||||||
|
|
||||||
|
debugPrint("2: Controllers initialized");
|
||||||
|
/*
|
||||||
|
// すべてのコントローラーとサービスを非同期で初期化
|
||||||
|
Get.lazyPut(() => IndexController(apiService: Get.find<ApiService>()));
|
||||||
|
debugPrint("2: start IndexController");
|
||||||
|
|
||||||
|
// その他のコントローラーを遅延初期化
|
||||||
|
Get.lazyPut(() => SettingsController());
|
||||||
|
debugPrint("2: start SettingsController");
|
||||||
|
Get.lazyPut(() => DestinationController());
|
||||||
|
debugPrint("3: start DestinationController");
|
||||||
|
Get.lazyPut(() => LocationController());
|
||||||
|
debugPrint("4: start LocationController");
|
||||||
|
*/
|
||||||
|
|
||||||
// 非同期処理を並列実行
|
// 非同期処理を並列実行
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
_initTimeZone(),
|
_initTimeZone(),
|
||||||
_initCacheProvider(),
|
_initCacheProvider(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
print('=== 5. Initialized TimeZone...');
|
print('=== 5. Initialized TimeZone...');
|
||||||
print('=== 6. CacheProvider started...');
|
print('=== 6. CacheProvider started...');
|
||||||
|
|
||||||
@ -520,6 +541,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
late final DestinationController _destinationController;
|
late final DestinationController _destinationController;
|
||||||
late final PermissionController _permissionController;
|
late final PermissionController _permissionController;
|
||||||
Timer? _memoryCheckTimer;
|
Timer? _memoryCheckTimer;
|
||||||
|
bool _isControllerInitialized = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -545,24 +567,94 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
// ここに他の初期化処理を追加できます
|
// ここに他の初期化処理を追加できます
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initializeControllers() {
|
Future <void> _initializeControllers() async {
|
||||||
|
|
||||||
|
while (!Get.isRegistered<LocationController>() ||
|
||||||
|
!Get.isRegistered<IndexController>() ||
|
||||||
|
!Get.isRegistered<DestinationController>() ||
|
||||||
|
!Get.isRegistered<PermissionController>()) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_isControllerInitialized) {
|
||||||
|
_locationController = Get.find<LocationController>();
|
||||||
|
_indexController = Get.find<IndexController>();
|
||||||
|
_destinationController = Get.find<DestinationController>();
|
||||||
|
_permissionController = Get.find<PermissionController>();
|
||||||
|
_isControllerInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (!Get.isRegistered<IndexController>()) {
|
while (true) {
|
||||||
|
try {
|
||||||
|
_locationController = Get.find<LocationController>();
|
||||||
|
break; // DestinationControllerが見つかったらループを抜ける
|
||||||
|
} catch (e) {
|
||||||
|
// DestinationControllerがまだ利用可能でない場合は少し待ってから再試行
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if (!Get.isRegistered<LocationController>()) {
|
||||||
_locationController = Get.put(LocationController(), permanent: true);
|
_locationController = Get.put(LocationController(), permanent: true);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
_indexController = Get.find<IndexController>();
|
||||||
|
break; // DestinationControllerが見つかったらループを抜ける
|
||||||
|
} catch (e) {
|
||||||
|
// DestinationControllerがまだ利用可能でない場合は少し待ってから再試行
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
if (!Get.isRegistered<IndexController>()) {
|
if (!Get.isRegistered<IndexController>()) {
|
||||||
_indexController = Get.put(IndexController(apiService: Get.find<ApiService>()), permanent: true);
|
_indexController = Get.put(IndexController(apiService: Get.find<ApiService>()), permanent: true);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
_destinationController = Get.find<DestinationController>();
|
||||||
|
break; // DestinationControllerが見つかったらループを抜ける
|
||||||
|
} catch (e) {
|
||||||
|
// DestinationControllerがまだ利用可能でない場合は少し待ってから再試行
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
if (!Get.isRegistered<DestinationController>()) {
|
if (!Get.isRegistered<DestinationController>()) {
|
||||||
_destinationController =
|
_destinationController =
|
||||||
Get.put(DestinationController(), permanent: true);
|
Get.put(DestinationController(), permanent: true);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
_permissionController = Get.find<PermissionController>();
|
||||||
|
break; // DestinationControllerが見つかったらループを抜ける
|
||||||
|
} catch (e) {
|
||||||
|
// DestinationControllerがまだ利用可能でない場合は少し待ってから再試行
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
if (!Get.isRegistered<PermissionController>()) {
|
if (!Get.isRegistered<PermissionController>()) {
|
||||||
_permissionController = Get.put(PermissionController());
|
_permissionController = Get.put(PermissionController());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// 他の必要なコントローラーの初期化
|
// 他の必要なコントローラーの初期化
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startMemoryMonitoring() {
|
void _startMemoryMonitoring() {
|
||||||
@ -677,6 +769,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_isControllerInitialized = false;
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_memoryCheckTimer?.cancel();
|
_memoryCheckTimer?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@ -704,6 +797,9 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AppLifecycleState.resumed:
|
case AppLifecycleState.resumed:
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
MotionService.startMotionUpdates();
|
||||||
|
}
|
||||||
//await _onResumed();
|
//await _onResumed();
|
||||||
await _onResumed();
|
await _onResumed();
|
||||||
break;
|
break;
|
||||||
@ -714,6 +810,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AppLifecycleState.paused:
|
case AppLifecycleState.paused:
|
||||||
|
MotionService.stopMotionUpdates();
|
||||||
// バックグラウンドに移行したときの処理
|
// バックグラウンドに移行したときの処理
|
||||||
//locationController.resumePositionStream();
|
//locationController.resumePositionStream();
|
||||||
await _onPaused();
|
await _onPaused();
|
||||||
@ -740,7 +837,9 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
Future<void> _onResumed() async {
|
Future<void> _onResumed() async {
|
||||||
debugPrint("==(Status Changed)==> RESUMED");
|
debugPrint("==(Status Changed)==> RESUMED");
|
||||||
try {
|
try {
|
||||||
_initializeControllers();
|
if (!_isControllerInitialized) {
|
||||||
|
await _initializeControllers();
|
||||||
|
}
|
||||||
|
|
||||||
await stopBackgroundTracking();
|
await stopBackgroundTracking();
|
||||||
_destinationController.restartGPS();
|
_destinationController.restartGPS();
|
||||||
|
|||||||
@ -311,7 +311,7 @@ class CameraPage extends StatelessWidget {
|
|||||||
? ElevatedButton(
|
? ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
|
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await destinationController.makeCheckin(destination, true,
|
await destinationController.makeCheckin(destination, true, // チェクインボタン
|
||||||
destinationController.photos[0].path);
|
destinationController.photos[0].path);
|
||||||
if( destinationController.isInRog.value==true ) {
|
if( destinationController.isInRog.value==true ) {
|
||||||
destinationController.rogainingCounted.value = true; // ロゲ開始後のみ許可
|
destinationController.rogainingCounted.value = true; // ロゲ開始後のみ許可
|
||||||
@ -526,7 +526,7 @@ class CameraPage extends StatelessWidget {
|
|||||||
// print(
|
// print(
|
||||||
|
|
||||||
// "##### current destination ${indexController.currentDestinationFeature[0].sub_loc_id} #######");
|
// "##### current destination ${indexController.currentDestinationFeature[0].sub_loc_id} #######");
|
||||||
await destinationController.makeCheckin(
|
await destinationController.makeCheckin( // チェックイン確定
|
||||||
indexController.currentDestinationFeature[0],
|
indexController.currentDestinationFeature[0],
|
||||||
true,
|
true,
|
||||||
destinationController.photos[0].path);
|
destinationController.photos[0].path);
|
||||||
@ -551,7 +551,7 @@ class CameraPage extends StatelessWidget {
|
|||||||
|
|
||||||
Navigator.of(context).pop(true); // ここを修正
|
Navigator.of(context).pop(true); // ここを修正
|
||||||
},
|
},
|
||||||
child: const Text("チェックイン"))
|
child: const Text("チェックイン確定"))
|
||||||
: Container())
|
: Container())
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -526,7 +526,7 @@ class DestinationController extends GetxController {
|
|||||||
debugPrint("** 自動チェックインの場合");
|
debugPrint("** 自動チェックインの場合");
|
||||||
//print(
|
//print(
|
||||||
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ make checkin ${d.sub_loc_id}@@@@@@@@@@@");
|
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ make checkin ${d.sub_loc_id}@@@@@@@@@@@");
|
||||||
makeCheckin(d, true, ""); // チェックインして
|
makeCheckin(d, true, ""); // 自動チェックイン
|
||||||
//if (d.cp != -1 && d.cp != -2 && d.cp != 0 ) {
|
//if (d.cp != -1 && d.cp != -2 && d.cp != 0 ) {
|
||||||
// rogainingCounted.value = true; // ゴール用チェックイン済み
|
// rogainingCounted.value = true; // ゴール用チェックイン済み
|
||||||
//}
|
//}
|
||||||
@ -750,9 +750,11 @@ class DestinationController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int? latgoal = await db.latestGoal();
|
int? latgoal = await db.latestGoal();
|
||||||
lastGoalAt = DateTime.fromMicrosecondsSinceEpoch(latgoal!);
|
if( latgoal != null ) {
|
||||||
debugPrint("===== last goal : $lastGoalAt =====");
|
lastGoalAt = DateTime.fromMicrosecondsSinceEpoch(latgoal!);
|
||||||
|
debugPrint("===== last goal : $lastGoalAt =====");
|
||||||
dbService.updateDatabase();
|
dbService.updateDatabase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// すべての目的地を削除する関数です。
|
// すべての目的地を削除する関数です。
|
||||||
@ -835,7 +837,7 @@ class DestinationController extends GetxController {
|
|||||||
print("---- f- checkin ${d.sub_loc_id} ----");
|
print("---- f- checkin ${d.sub_loc_id} ----");
|
||||||
if (autoCheckin) {
|
if (autoCheckin) {
|
||||||
if (!checkingIn) {
|
if (!checkingIn) {
|
||||||
makeCheckin(d, true, "");
|
makeCheckin(d, true, ""); // callforCheckin
|
||||||
if (d.cp != -1 && d.cp != 0 && d.cp != -2) {
|
if (d.cp != -1 && d.cp != 0 && d.cp != -2) {
|
||||||
rogainingCounted.value = true;
|
rogainingCounted.value = true;
|
||||||
}
|
}
|
||||||
@ -1085,12 +1087,13 @@ class DestinationController extends GetxController {
|
|||||||
// ロゲイニングにデータを追加する関数です。
|
// ロゲイニングにデータを追加する関数です。
|
||||||
//
|
//
|
||||||
void addToRogaining(double lat, double lon, int destinationId) async {
|
void addToRogaining(double lat, double lon, int destinationId) async {
|
||||||
|
debugPrint("addToRogaining .... ");
|
||||||
DatabaseHelper db = DatabaseHelper.instance;
|
DatabaseHelper db = DatabaseHelper.instance;
|
||||||
List<Destination> d = await db.getDestinationById(destinationId);
|
List<Destination> d = await db.getDestinationById(destinationId);
|
||||||
if (d.isEmpty) {
|
if (d.isEmpty) {
|
||||||
Destination df = festuretoDestination(indexController.currentFeature[0]);
|
Destination df = festuretoDestination(indexController.currentFeature[0]);
|
||||||
//print("--- made checkin ${df.location_id} ----");
|
//print("--- made checkin ${df.location_id} ----");
|
||||||
makeCheckin(df, true, "");
|
makeCheckin(df, true, ""); // addToRogaining
|
||||||
}
|
}
|
||||||
isInRog.value = true;
|
isInRog.value = true;
|
||||||
|
|
||||||
@ -1138,10 +1141,10 @@ class DestinationController extends GetxController {
|
|||||||
|
|
||||||
// ギャラリーにも保存
|
// ギャラリーにも保存
|
||||||
//await ImageGallerySaver.saveFile(savedImage.path);
|
//await ImageGallerySaver.saveFile(savedImage.path);
|
||||||
await Future.delayed(const Duration(seconds: 3), () async {
|
await Future.delayed(const Duration(seconds: 5), () async {
|
||||||
final result = await ImageGallerySaver.saveFile(savedImage.path);
|
final result = await ImageGallerySaver.saveFile(savedImage.path);
|
||||||
print("Save result: $result");
|
print("Save result: $result");
|
||||||
}).timeout(const Duration(seconds: 5));
|
}).timeout(const Duration(seconds: 7));
|
||||||
|
|
||||||
|
|
||||||
debugPrint('Image saved to: ${savedImage.path}');
|
debugPrint('Image saved to: ${savedImage.path}');
|
||||||
@ -1214,14 +1217,16 @@ class DestinationController extends GetxController {
|
|||||||
// print(
|
// print(
|
||||||
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ressssss ${destination.sub_loc_id}@@@@@@@@@@@");
|
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ressssss ${destination.sub_loc_id}@@@@@@@@@@@");
|
||||||
DatabaseHelper db = DatabaseHelper.instance;
|
DatabaseHelper db = DatabaseHelper.instance;
|
||||||
List<Destination> ddd =
|
List<Destination> ddd = await db.getDestinationByLatLon(destination.lat!, destination.lon!);
|
||||||
await db.getDestinationByLatLon(destination.lat!, destination.lon!);
|
|
||||||
|
|
||||||
if (ddd.isEmpty) {
|
if (ddd.isEmpty) {
|
||||||
destination.checkedin = true;
|
destination.checkedin = true;
|
||||||
|
debugPrint("...近くにCPがないのにチェックイン?...makeCheckin imageUrl = $imageurl");
|
||||||
if (imageurl.isNotEmpty) {
|
if (imageurl.isNotEmpty) {
|
||||||
String? savedImagePath = await _saveImageToGallery(imageurl);
|
String? savedImagePath = await _saveImageToGallery(imageurl);
|
||||||
destination.checkin_image = savedImagePath ?? imageurl;
|
destination.checkin_image = savedImagePath ?? imageurl;
|
||||||
|
}else{
|
||||||
|
debugPrint("makeCheckin ... No image...");
|
||||||
}
|
}
|
||||||
await db.insertDestination(destination);
|
await db.insertDestination(destination);
|
||||||
// print("~~~~ inserted into db ~~~~");
|
// print("~~~~ inserted into db ~~~~");
|
||||||
@ -1229,15 +1234,18 @@ class DestinationController extends GetxController {
|
|||||||
|
|
||||||
if (imageurl.isEmpty) {
|
if (imageurl.isEmpty) {
|
||||||
if (photos.isNotEmpty) {
|
if (photos.isNotEmpty) {
|
||||||
|
debugPrint("imageurlが空の場合は、destinationのcheckin_imageプロパティを使用する");
|
||||||
// imageurlが空の場合は、destinationのcheckin_imageプロパティを使用する
|
// imageurlが空の場合は、destinationのcheckin_imageプロパティを使用する
|
||||||
debugPrint("photos = $photos");
|
//debugPrint("photos = $photos");
|
||||||
imageurl = photos[0].path;
|
//imageurl = photos[0].path;
|
||||||
}
|
}
|
||||||
debugPrint("imageurl = $imageurl");
|
debugPrint("imageurl = $imageurl");
|
||||||
//await _saveImageFromPath(imageurl!);
|
//await _saveImageFromPath(imageurl!);
|
||||||
}
|
}
|
||||||
if (imageurl.isNotEmpty) {
|
if (imageurl.isNotEmpty) {
|
||||||
|
debugPrint("...これでアルバム保存...makeCheckin imageUrl = $imageurl");
|
||||||
String? savedImagePath = await _saveImageToGallery(imageurl);
|
String? savedImagePath = await _saveImageToGallery(imageurl);
|
||||||
|
debugPrint("イメージのアルバム保存完了!!");
|
||||||
destination.checkin_image = savedImagePath ?? imageurl;
|
destination.checkin_image = savedImagePath ?? imageurl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -96,6 +96,8 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
final selectedEventName = 'add_location'.tr.obs;
|
final selectedEventName = 'add_location'.tr.obs;
|
||||||
|
|
||||||
|
RxBool isLoadingLocations = true.obs;
|
||||||
|
|
||||||
void setSelectedEventName(String eventName) {
|
void setSelectedEventName(String eventName) {
|
||||||
selectedEventName.value = eventName;
|
selectedEventName.value = eventName;
|
||||||
}
|
}
|
||||||
@ -256,6 +258,9 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
tz.initializeTimeZones();
|
tz.initializeTimeZones();
|
||||||
//teamController = Get.find<TeamController>();
|
//teamController = Get.find<TeamController>();
|
||||||
|
|
||||||
|
loadLocations();
|
||||||
|
|
||||||
}catch(e,stacktrace){
|
}catch(e,stacktrace){
|
||||||
print('Error in IndexController.onInit: $e');
|
print('Error in IndexController.onInit: $e');
|
||||||
print('Stack trace: $stacktrace');
|
print('Stack trace: $stacktrace');
|
||||||
@ -265,6 +270,20 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> loadLocations() async {
|
||||||
|
isLoadingLocations.value = true;
|
||||||
|
try {
|
||||||
|
await waitForMapControllerReady();
|
||||||
|
String eventCode = currentUser.isNotEmpty ? currentUser[0]["user"]["event_code"] ?? "" : "";
|
||||||
|
await loadLocationsBound(eventCode);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error loading locations: $e');
|
||||||
|
// エラーハンドリングを追加(例:スナックバーでユーザーに通知)
|
||||||
|
} finally {
|
||||||
|
isLoadingLocations.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _updateConnectionStatus(List<ConnectivityResult> results) {
|
void _updateConnectionStatus(List<ConnectivityResult> results) {
|
||||||
|
|
||||||
final result = results.isNotEmpty ? results.first : ConnectivityResult.none;
|
final result = results.isNotEmpty ? results.first : ConnectivityResult.none;
|
||||||
@ -873,7 +892,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
// 要検討:Future.delayedを使用して非同期処理を待たずに先に進むようにしていますが、
|
// 要検討:Future.delayedを使用して非同期処理を待たずに先に進むようにしていますが、
|
||||||
// これによってメモリリークが発生する可能性があります。非同期処理の結果を適切に処理することを検討してください。
|
// これによってメモリリークが発生する可能性があります。非同期処理の結果を適切に処理することを検討してください。
|
||||||
//
|
//
|
||||||
void loadLocationsBound(String eventCode) async {
|
Future<void> loadLocationsBound(String eventCode) async {
|
||||||
if (isCustomAreaSelected.value == true) {
|
if (isCustomAreaSelected.value == true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -881,6 +900,19 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
// MapControllerの初期化が完了するまで待機
|
// MapControllerの初期化が完了するまで待機
|
||||||
await waitForMapControllerReady();
|
await waitForMapControllerReady();
|
||||||
|
|
||||||
|
// null チェックを追加
|
||||||
|
if (mapController.bounds == null) {
|
||||||
|
print("MapController bounds are null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// バウンドが有効かどうかを確認する
|
||||||
|
LatLngBounds bounds = mapController.bounds!;
|
||||||
|
if (!_isValidBounds(bounds)) {
|
||||||
|
print("MapController bounds are not valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
locations.clear();
|
locations.clear();
|
||||||
String cat = currentCat.isNotEmpty ? currentCat[0] : "";
|
String cat = currentCat.isNotEmpty ? currentCat[0] : "";
|
||||||
if (currentCat.isNotEmpty && currentCat[0] == "-all-") {
|
if (currentCat.isNotEmpty && currentCat[0] == "-all-") {
|
||||||
@ -896,7 +928,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
//
|
//
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LatLngBounds bounds = mapController.bounds!;
|
//LatLngBounds bounds = mapController.bounds!;
|
||||||
|
|
||||||
currentBound.clear();
|
currentBound.clear();
|
||||||
currentBound.add(bounds);
|
currentBound.add(bounds);
|
||||||
@ -987,6 +1019,15 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// バウンドが有効かどうかを確認するヘルパーメソッド
|
||||||
|
bool _isValidBounds(LatLngBounds bounds) {
|
||||||
|
// 緯度と経度が有効な範囲内にあるかチェック
|
||||||
|
return bounds.southWest.latitude.abs() <= 90 &&
|
||||||
|
bounds.southWest.longitude.abs() <= 180 &&
|
||||||
|
bounds.northEast.latitude.abs() <= 90 &&
|
||||||
|
bounds.northEast.longitude.abs() <= 180 &&
|
||||||
|
bounds.southWest.latitude < bounds.northEast.latitude;
|
||||||
|
}
|
||||||
|
|
||||||
//===Akira 追加:2024-4-6 #2800
|
//===Akira 追加:2024-4-6 #2800
|
||||||
// 要検討:MapControllerの初期化が完了するまで待機していますが、タイムアウトを設定することを検討してください。
|
// 要検討:MapControllerの初期化が完了するまで待機していますが、タイムアウトを設定することを検討してください。
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import 'package:gifunavi/widgets/list_widget.dart';
|
|||||||
import 'package:gifunavi/widgets/map_widget.dart';
|
import 'package:gifunavi/widgets/map_widget.dart';
|
||||||
import 'package:gifunavi/utils/location_controller.dart';
|
import 'package:gifunavi/utils/location_controller.dart';
|
||||||
|
|
||||||
|
import '../permission/permission.dart';
|
||||||
|
|
||||||
// index_page.dartファイルの主な内容です。
|
// index_page.dartファイルの主な内容です。
|
||||||
// このファイルは、アプリのメインページのUIを構築し、各機能へのナビゲーションを提供しています。
|
// このファイルは、アプリのメインページのUIを構築し、各機能へのナビゲーションを提供しています。
|
||||||
// また、IndexControllerとDestinationControllerを使用して、状態管理と各種機能の実装を行っています。
|
// また、IndexControllerとDestinationControllerを使用して、状態管理と各種機能の実装を行っています。
|
||||||
@ -36,12 +38,20 @@ class _IndexPageState extends State<IndexPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
//checkLoginAndShowDialog();
|
await _ensureControllersAreInitialized();
|
||||||
//checkEventAndNavigate();
|
await PermissionController.checkAndRequestPermissions();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _ensureControllersAreInitialized() async {
|
||||||
|
while (!Get.isRegistered<IndexController>() ||
|
||||||
|
!Get.isRegistered<DestinationController>() ||
|
||||||
|
!Get.isRegistered<LocationController>()) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void checkEventAndNavigate() async {
|
void checkEventAndNavigate() async {
|
||||||
if (indexController.currentUser.isNotEmpty &&
|
if (indexController.currentUser.isNotEmpty &&
|
||||||
indexController.currentUser[0]["user"]["event_code"] == null) {
|
indexController.currentUser[0]["user"]["event_code"] == null) {
|
||||||
|
|||||||
@ -126,28 +126,27 @@ class PermissionController {
|
|||||||
_isRequestingPermission = true;
|
_isRequestingPermission = true;
|
||||||
_permissionCompleter = Completer<bool>();
|
_permissionCompleter = Completer<bool>();
|
||||||
|
|
||||||
bool hasPermissions = await _checkLocationPermissions();
|
try {
|
||||||
if (!hasPermissions) {
|
bool hasPermissions = await _checkLocationPermissions();
|
||||||
bool userAgreed = await showLocationDisclosure();
|
if (!hasPermissions) {
|
||||||
if (userAgreed) {
|
bool userAgreed = await showLocationDisclosure();
|
||||||
try {
|
if (userAgreed) {
|
||||||
await requestAllLocationPermissions();
|
hasPermissions = await _requestAllLocationPermissions();
|
||||||
hasPermissions = await _checkLocationPermissions();
|
} else {
|
||||||
} catch (e) {
|
print('User did not agree to location usage');
|
||||||
print('Error requesting location permissions: $e');
|
|
||||||
hasPermissions = false;
|
hasPermissions = false;
|
||||||
|
// アプリを終了
|
||||||
|
SystemNavigator.pop();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print('User did not agree to location usage');
|
|
||||||
hasPermissions = false;
|
|
||||||
// アプリを終了
|
|
||||||
SystemNavigator.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isRequestingPermission = false;
|
||||||
|
_permissionCompleter!.complete(hasPermissions);
|
||||||
|
} catch( e ) {
|
||||||
|
print('Error in permission request: $e');
|
||||||
|
_isRequestingPermission = false;
|
||||||
|
_permissionCompleter!.complete(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isRequestingPermission = false;
|
|
||||||
_permissionCompleter!.complete(hasPermissions);
|
|
||||||
|
|
||||||
debugPrint("Finish checkAndRequestPermissions...");
|
debugPrint("Finish checkAndRequestPermissions...");
|
||||||
return _permissionCompleter!.future;
|
return _permissionCompleter!.future;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,7 +108,22 @@ class AuthService {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
cats = json.decode(utf8.decode(response.bodyBytes));
|
cats = json.decode(utf8.decode(response.bodyBytes));
|
||||||
} else {
|
} else {
|
||||||
|
debugPrint('Response body: ${response.body}');
|
||||||
|
|
||||||
print('Login failed with status code: ${response.statusCode}');
|
print('Login failed with status code: ${response.statusCode}');
|
||||||
|
var errorMessage = 'ログインに失敗しました。';
|
||||||
|
if (response.statusCode == 400) {
|
||||||
|
var errorBody = json.decode(utf8.decode(response.bodyBytes));
|
||||||
|
errorMessage = errorBody['non_field_errors']?[0] ?? 'パスワードが正しくありません。';
|
||||||
|
}
|
||||||
|
Get.snackbar(
|
||||||
|
"エラー",
|
||||||
|
errorMessage,
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
colorText: Colors.white,
|
||||||
|
snackPosition: SnackPosition.TOP,
|
||||||
|
duration: const Duration(seconds: 3),
|
||||||
|
);
|
||||||
cats = {};
|
cats = {};
|
||||||
}
|
}
|
||||||
} catch( e ){
|
} catch( e ){
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class ExternalService {
|
|||||||
<String, String>{'team_name': team, 'event_code': eventCode}),
|
<String, String>{'team_name': team, 'event_code': eventCode}),
|
||||||
);
|
);
|
||||||
|
|
||||||
//print("---- start rogianing api status ---- ${response.statusCode}");
|
print("---- start rogianing api status ---- ${response.statusCode}");
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
res = json.decode(utf8.decode(response.bodyBytes));
|
res = json.decode(utf8.decode(response.bodyBytes));
|
||||||
|
|||||||
29
lib/services/motion_service.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
class MotionService {
|
||||||
|
static const MethodChannel _channel = MethodChannel('net.sumasen.gifunavi/motion');
|
||||||
|
|
||||||
|
static Future<void> startMotionUpdates() async {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('startMotionUpdates');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print("Failed to start motion updates: '${e.message}'.");
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
// Android の場合は何もしない、またはAndroid向けの代替実装を行う
|
||||||
|
print("Motion updates not supported on this platform");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> stopMotionUpdates() async {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('stopMotionUpdates');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print("Failed to stop motion updates: '${e.message}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -139,16 +139,23 @@ class BottomSheetNew extends GetView<BottomSheetController> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveTemporaryImage(Destination destination) async {
|
Future<void> saveTemporaryImage(Destination destination) async {
|
||||||
final serverUrl = ConstValues.currentServer();
|
try {
|
||||||
final imagePath = '$serverUrl/media/compressed/${destination.photos}';
|
final serverUrl = ConstValues.currentServer();
|
||||||
|
final imagePath = '$serverUrl/media/compressed/${destination.photos}';
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
debugPrint("imagePath = $imagePath");
|
||||||
final tempFile = await File('${tempDir.path}/temp_image.jpg').create(recursive: true);
|
|
||||||
final response = await http.get(Uri.parse(imagePath));
|
|
||||||
await tempFile.writeAsBytes(response.bodyBytes);
|
|
||||||
|
|
||||||
destinationController.photos.clear();
|
final tempDir = await getTemporaryDirectory();
|
||||||
destinationController.photos.add(tempFile);
|
final tempFile = await File('${tempDir.path}/temp_image.jpg').create(
|
||||||
|
recursive: true);
|
||||||
|
final response = await http.get(Uri.parse(imagePath));
|
||||||
|
await tempFile.writeAsBytes(response.bodyBytes);
|
||||||
|
|
||||||
|
destinationController.photos.clear();
|
||||||
|
destinationController.photos.add(tempFile);
|
||||||
|
} catch( e ) {
|
||||||
|
debugPrint("saveTemporaryImage error : $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// アクションボタン(チェックイン、ゴールなど)を表示するためのメソッドです。
|
// アクションボタン(チェックイン、ゴールなど)を表示するためのメソッドです。
|
||||||
@ -239,12 +246,8 @@ class BottomSheetNew extends GetView<BottomSheetController> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
destinationController.isInRog.value = true;
|
destinationController.isInRog.value = true;
|
||||||
|
|
||||||
|
|
||||||
// Show confirmation dialog
|
// Show confirmation dialog
|
||||||
Get.dialog(
|
Get.dialog(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
@ -270,6 +273,7 @@ class BottomSheetNew extends GetView<BottomSheetController> {
|
|||||||
// Clear data and start game logic here
|
// Clear data and start game logic here
|
||||||
destinationController.resetRogaining();
|
destinationController.resetRogaining();
|
||||||
|
|
||||||
|
// ここでチェックインもしている。
|
||||||
destinationController.addToRogaining(
|
destinationController.addToRogaining(
|
||||||
destinationController.currentLat,
|
destinationController.currentLat,
|
||||||
destinationController.currentLon,
|
destinationController.currentLon,
|
||||||
@ -996,15 +1000,12 @@ class BottomSheetNew extends GetView<BottomSheetController> {
|
|||||||
Obx((() => indexController.rogMode.value == 1
|
Obx((() => indexController.rogMode.value == 1
|
||||||
? ElevatedButton(
|
? ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Destination dest =
|
Destination dest = indexController.currentDestinationFeature[0];
|
||||||
indexController.currentDestinationFeature[0];
|
print("~~~~ before checking button ~~~~");
|
||||||
//print("~~~~ before checking button ~~~~");
|
|
||||||
//print("------ curent destination is ${dest!.checkedIn}-------");
|
//print("------ curent destination is ${dest!.checkedIn}-------");
|
||||||
destinationController.makeCheckin(
|
destinationController.makeCheckin( dest, !dest.checkedin!, "");
|
||||||
dest, !dest.checkedin!, "");
|
|
||||||
},
|
},
|
||||||
child: indexController
|
child: indexController.currentDestinationFeature[0].checkedin ==
|
||||||
.currentDestinationFeature[0].checkedin ==
|
|
||||||
false
|
false
|
||||||
? const Text("チェックイン")
|
? const Text("チェックイン")
|
||||||
: const Text("チェックアウト"))
|
: const Text("チェックアウト"))
|
||||||
|
|||||||
@ -140,12 +140,25 @@ class _MapWidgetState extends State<MapWidget> with WidgetsBindingObserver {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// _centerMapOnUser を10秒間でコール
|
// _centerMapOnUser を10秒間でコール
|
||||||
void _startIdleTimer() {
|
Future<void> _startIdleTimer() async {
|
||||||
//debugPrint("_startIdleTimer ....");
|
//debugPrint("_startIdleTimer ....");
|
||||||
final settingsController = Get.find<SettingsController>();
|
SettingsController settingsController;
|
||||||
|
|
||||||
|
// SettingsControllerが利用可能になるまで待機
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
settingsController = Get.find<SettingsController>();
|
||||||
|
break; // SettingsControllerが見つかったらループを抜ける
|
||||||
|
} catch (e) {
|
||||||
|
// SettingsControllerがまだ利用可能でない場合は少し待ってから再試行
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!settingsController.autoReturnDisabled.value) {
|
if (!settingsController.autoReturnDisabled.value) {
|
||||||
_timer = Timer(settingsController.timerDuration.value, _centerMapOnUser);
|
_timer = Timer(settingsController.timerDuration.value, _centerMapOnUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// タイマーをリセットして_startIdleTimer をコール
|
// タイマーをリセットして_startIdleTimer をコール
|
||||||
@ -173,7 +186,16 @@ class _MapWidgetState extends State<MapWidget> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
Future<List<Marker>> _getMarkers() async {
|
Future<List<Marker>> _getMarkers() async {
|
||||||
debugPrint('Getting markers...');
|
debugPrint('Getting markers...');
|
||||||
List<Marker> markers = [];
|
if (indexController.isLoadingLocations.value) {
|
||||||
|
await Future.doWhile(() async {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
return indexController.isLoadingLocations.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('Getting markers...');
|
||||||
|
|
||||||
|
List<Marker> markers = [];
|
||||||
if (indexController.locations.isNotEmpty && indexController.locations[0].features.isNotEmpty) {
|
if (indexController.locations.isNotEmpty && indexController.locations[0].features.isNotEmpty) {
|
||||||
for (var feature in indexController.locations[0].features) {
|
for (var feature in indexController.locations[0].features) {
|
||||||
GeoJSONMultiPoint point = feature!.geometry as GeoJSONMultiPoint;
|
GeoJSONMultiPoint point = feature!.geometry as GeoJSONMultiPoint;
|
||||||
|
|||||||