WIP #49
This commit is contained in:
parent
b112ff980a
commit
bc1a791608
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,4 +11,5 @@ build/
|
|||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
key.properties
|
key.properties
|
||||||
|
premium_features_manager.class.dart
|
||||||
pubspec.lock
|
pubspec.lock
|
@ -7,6 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
|
||||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
@ -14,7 +15,7 @@
|
|||||||
additional functionality it is fine to subclass or reimplement
|
additional functionality it is fine to subclass or reimplement
|
||||||
FlutterApplication and put your custom class here. -->
|
FlutterApplication and put your custom class here. -->
|
||||||
<application
|
<application
|
||||||
android:name="io.flutter.app.FlutterApplication"
|
android:name=".Application"
|
||||||
android:label="HA Client"
|
android:label="HA Client"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true">
|
||||||
@ -46,5 +47,12 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<receiver android:name="com.lyokone.location.BackgroundLocationBroadcastReceiver"
|
||||||
|
android:enabled="true" android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.lyokone.location.BackgroundLocationBroadcastReceiver.ACTION_PROCESS_UPDATES" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.keyboardcrumbs.hassclient;
|
||||||
|
|
||||||
|
import io.flutter.app.FlutterApplication;
|
||||||
|
import io.flutter.plugin.common.PluginRegistry;
|
||||||
|
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
|
||||||
|
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||||
|
import com.lyokone.location.LocationPlugin;
|
||||||
|
|
||||||
|
public class Application extends FlutterApplication implements PluginRegistrantCallback {
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
LocationPlugin.setPluginRegistrant(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerWith(PluginRegistry registry) {
|
||||||
|
GeneratedPluginRegistrant.registerWith(registry);
|
||||||
|
}
|
||||||
|
}
|
41
flutter_01.log
Normal file
41
flutter_01.log
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Flutter crash report; please file at https://github.com/flutter/flutter/issues.
|
||||||
|
|
||||||
|
## command
|
||||||
|
|
||||||
|
flutter --no-color run --machine --track-widget-creation --device-id=89AY052S4 lib/main.dart
|
||||||
|
|
||||||
|
## exception
|
||||||
|
|
||||||
|
_InternalLinkedHashMap<String, dynamic>: {code: 105, message: Isolate must be runnable, data: {request: {method: _reloadSources, params: {pause: true, rootLibUri: file:///data/user/0/com.keyboardcrumbs.haclient/code_cache/ha_clientSYJJZI/ha_client/lib/main.dart.incremental.dill, packagesUri: file:///data/user/0/com.keyboardcrumbs.haclient/code_cache/ha_clientSYJJZI/ha_client/.packages, isolateId: isolates/68989666}}, details: Isolate must be runnable before this request is made.}}
|
||||||
|
|
||||||
|
```
|
||||||
|
null```
|
||||||
|
|
||||||
|
## flutter doctor
|
||||||
|
|
||||||
|
```
|
||||||
|
[✓] Flutter (Channel stable, v1.7.8+hotfix.4, on Linux, locale en_US.UTF-8)
|
||||||
|
• Flutter version 1.7.8+hotfix.4 at /home/estevez/sdk/flutter
|
||||||
|
• Framework revision 20e59316b8 (6 weeks ago), 2019-07-18 20:04:33 -0700
|
||||||
|
• Engine revision fee001c93f
|
||||||
|
• Dart version 2.4.0
|
||||||
|
|
||||||
|
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
|
||||||
|
• Android SDK at /home/estevez/Android/Sdk
|
||||||
|
• Android NDK location not configured (optional; useful for native profiling support)
|
||||||
|
• Platform android-29, build-tools 29.0.2
|
||||||
|
• Java binary at: /home/estevez/bin/android-studio/jre/bin/java
|
||||||
|
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
|
||||||
|
• All Android licenses accepted.
|
||||||
|
|
||||||
|
[✓] Android Studio (version 3.5)
|
||||||
|
• Android Studio at /home/estevez/bin/android-studio
|
||||||
|
• Flutter plugin version 38.2.3
|
||||||
|
• Dart plugin version 191.8423
|
||||||
|
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
|
||||||
|
|
||||||
|
[✓] Connected device (1 available)
|
||||||
|
• Pixel 3 XL • 89AY052S4 • android-arm64 • Android 9 (API 28)
|
||||||
|
|
||||||
|
• No issues found!
|
||||||
|
```
|
@ -15,7 +15,6 @@ import 'package:http/http.dart' as http;
|
|||||||
import 'package:charts_flutter/flutter.dart' as charts;
|
import 'package:charts_flutter/flutter.dart' as charts;
|
||||||
import 'package:progress_indicators/progress_indicators.dart';
|
import 'package:progress_indicators/progress_indicators.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
//import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
|
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
|
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
|
||||||
@ -23,8 +22,10 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|||||||
import 'package:device_info/device_info.dart';
|
import 'package:device_info/device_info.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:in_app_purchase/in_app_purchase.dart';
|
import 'package:in_app_purchase/in_app_purchase.dart';
|
||||||
|
import 'package:location/location.dart';
|
||||||
|
|
||||||
part 'const.dart';
|
part 'const.dart';
|
||||||
|
part 'premium_features_manager.class.dart';
|
||||||
part 'entities/entity.class.dart';
|
part 'entities/entity.class.dart';
|
||||||
part 'entities/entity_wrapper.class.dart';
|
part 'entities/entity_wrapper.class.dart';
|
||||||
part 'entities/timer/timer_entity.class.dart';
|
part 'entities/timer/timer_entity.class.dart';
|
||||||
@ -118,7 +119,7 @@ FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLoc
|
|||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersion = "0.6.4";
|
const appVersion = "0.6.4";
|
||||||
|
|
||||||
void main() {
|
void main() async {
|
||||||
FlutterError.onError = (errorDetails) {
|
FlutterError.onError = (errorDetails) {
|
||||||
Logger.e( "${errorDetails.exception}");
|
Logger.e( "${errorDetails.exception}");
|
||||||
if (Logger.isInDebugMode) {
|
if (Logger.isInDebugMode) {
|
||||||
@ -127,7 +128,9 @@ void main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
runZoned(() {
|
runZoned(() {
|
||||||
|
|
||||||
runApp(new HAClientApp());
|
runApp(new HAClientApp());
|
||||||
|
|
||||||
}, onError: (error, stack) {
|
}, onError: (error, stack) {
|
||||||
Logger.e("$error");
|
Logger.e("$error");
|
||||||
Logger.e("$stack");
|
Logger.e("$stack");
|
||||||
@ -239,6 +242,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
||||||
onSelectNotification: onSelectNotification);
|
onSelectNotification: onSelectNotification);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
|
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
|
||||||
Logger.d("Settings change event: reconnect=${event.reconnect}");
|
Logger.d("Settings change event: reconnect=${event.reconnect}");
|
||||||
if (event.reconnect) {
|
if (event.reconnect) {
|
||||||
@ -247,6 +252,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
});
|
});
|
||||||
|
|
||||||
_fullLoad();
|
_fullLoad();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future onSelectNotification(String payload) async {
|
Future onSelectNotification(String payload) async {
|
||||||
@ -274,6 +281,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_showInfoBottomBar(progress: true,);
|
_showInfoBottomBar(progress: true,);
|
||||||
_subscribe().then((_) {
|
_subscribe().then((_) {
|
||||||
Connection().init(loadSettings: true, forceReconnect: true).then((__){
|
Connection().init(loadSettings: true, forceReconnect: true).then((__){
|
||||||
|
PremiumFeaturesManager();
|
||||||
_fetchData();
|
_fetchData();
|
||||||
}, onError: (e) {
|
}, onError: (e) {
|
||||||
_setErrorState(e);
|
_setErrorState(e);
|
||||||
@ -321,6 +329,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
void _handlePurchaseUpdates(purchase) {
|
void _handlePurchaseUpdates(purchase) {
|
||||||
if (purchase is List<PurchaseDetails>) {
|
if (purchase is List<PurchaseDetails>) {
|
||||||
if (purchase[0].status == PurchaseStatus.purchased) {
|
if (purchase[0].status == PurchaseStatus.purchased) {
|
||||||
|
PremiumFeaturesManager().updatePurchases(purchase[0]);
|
||||||
eventBus.fire(ShowPopupMessageEvent(
|
eventBus.fire(ShowPopupMessageEvent(
|
||||||
title: "Thanks a lot!",
|
title: "Thanks a lot!",
|
||||||
body: "Thank you for supporting HA Client development!",
|
body: "Thank you for supporting HA Client development!",
|
||||||
@ -752,6 +761,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
|
|
||||||
Widget _buildScaffoldBody(bool empty) {
|
Widget _buildScaffoldBody(bool empty) {
|
||||||
List<PopupMenuItem<String>> popupMenuItems = [];
|
List<PopupMenuItem<String>> popupMenuItems = [];
|
||||||
|
|
||||||
popupMenuItems.add(PopupMenuItem<String>(
|
popupMenuItems.add(PopupMenuItem<String>(
|
||||||
child: new Text("Reload"),
|
child: new Text("Reload"),
|
||||||
value: "reload",
|
value: "reload",
|
||||||
|
@ -10,66 +10,29 @@ class PurchasePage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PurchasePageState extends State<PurchasePage> {
|
class _PurchasePageState extends State<PurchasePage> {
|
||||||
|
|
||||||
bool _loaded = false;
|
bool _loaded = false;
|
||||||
String _error = "";
|
String _error = "";
|
||||||
List<ProductDetails> _products;
|
|
||||||
List<PurchaseDetails> _purchases;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadProducts();
|
if (PremiumFeaturesManager().products.isEmpty) {
|
||||||
}
|
_error = "Subscription is not loaded";
|
||||||
|
|
||||||
_loadProducts() async {
|
|
||||||
final bool available = await InAppPurchaseConnection.instance.isAvailable();
|
|
||||||
if (!available) {
|
|
||||||
setState(() {
|
|
||||||
_error = "Error connecting to store";
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const Set<String> _kIds = {'just_few_bucks_per_year', 'app_fan_support_per_year', 'grateful_user_support_per_year'};
|
_loaded = true;
|
||||||
final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
|
|
||||||
if (!response.notFoundIDs.isEmpty) {
|
|
||||||
Logger.d("Products not found: ${response.notFoundIDs}");
|
|
||||||
}
|
|
||||||
_products = response.productDetails;
|
|
||||||
_loadPreviousPurchases();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadPreviousPurchases() async {
|
|
||||||
final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
|
|
||||||
if (response.error != null) {
|
|
||||||
setState(() {
|
|
||||||
_error = "Error loading previous purchases";
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
_purchases = response.pastPurchases;
|
|
||||||
for (PurchaseDetails purchase in _purchases) {
|
|
||||||
Logger.d("Previous purchase: ${purchase.status}");
|
|
||||||
}
|
|
||||||
if (_products.isEmpty) {
|
|
||||||
setState(() {
|
|
||||||
_error = "No data found in store";
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setState(() {
|
|
||||||
_loaded = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildProducts() {
|
Widget _buildProducts() {
|
||||||
List<Widget> productWidgets = [];
|
List<Widget> productWidgets = [];
|
||||||
for (ProductDetails product in _products) {
|
for (ProductDetails product in PremiumFeaturesManager().products) {
|
||||||
productWidgets.add(
|
productWidgets.add(
|
||||||
ProductPurchase(
|
ProductPurchase(
|
||||||
product: product,
|
product: product,
|
||||||
onBuy: (product) => _buyProduct(product),
|
onBuy: (product) => _buyProduct(product),
|
||||||
purchased: _purchases.any((purchase) { return purchase.productID == product.id;}),)
|
purchased: PremiumFeaturesManager().purchases.any((purchase) { return purchase.productID == product.id;}),)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListView(
|
return ListView(
|
||||||
|
17
pubspec.lock
17
pubspec.lock
@ -49,14 +49,14 @@ packages:
|
|||||||
name: charts_common
|
name: charts_common
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.7.0"
|
||||||
charts_flutter:
|
charts_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: charts_flutter
|
name: charts_flutter
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.7.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -77,7 +77,7 @@ packages:
|
|||||||
name: crypto
|
name: crypto
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1+1"
|
version: "2.1.2"
|
||||||
date_format:
|
date_format:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -207,6 +207,15 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "2.4.0"
|
||||||
|
location:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: background_location
|
||||||
|
resolved-ref: "7c089fad38acbb7be7c46f207f601ac8e6b21caf"
|
||||||
|
url: "git://github.com/Lyokone/flutterlocation.git"
|
||||||
|
source: git
|
||||||
|
version: "2.3.5"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -309,7 +318,7 @@ packages:
|
|||||||
name: sqflite
|
name: sqflite
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.6+3"
|
version: "1.1.6+4"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -26,6 +26,11 @@ dependencies:
|
|||||||
flutter_secure_storage: ^3.2.1+1
|
flutter_secure_storage: ^3.2.1+1
|
||||||
device_info: ^0.4.0+2
|
device_info: ^0.4.0+2
|
||||||
flutter_local_notifications: ^0.8.2
|
flutter_local_notifications: ^0.8.2
|
||||||
|
location:
|
||||||
|
git:
|
||||||
|
url: git://github.com/Lyokone/flutterlocation.git
|
||||||
|
ref: background_location
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user