WT 1.1.7+2 SearchBar, Timer for ExerciseControl

This commit is contained in:
bossanyit
2021-02-28 17:03:47 +01:00
parent cf348cebb0
commit 6bea5e70e1
77 changed files with 1581 additions and 1008 deletions
+68
View File
@@ -0,0 +1,68 @@
import 'dart:io';
import 'package:aitrainer_app/service/logging.dart';
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AppLanguage with Logging {
static final AppLanguage _singleton = AppLanguage._internal();
Locale _appLocale = Locale('en');
factory AppLanguage() {
return _singleton;
}
AppLanguage._internal();
static Future<AppLanguage> getInstance() async {
return _singleton;
}
Locale get appLocal => _appLocale ?? Locale("en");
Future<void> fetchLocale() async {
var prefs = await SharedPreferences.getInstance();
String langCode = prefs.getString('language_code');
log(" ---- lang code $langCode");
if (langCode == null) {
_appLocale = Locale('en');
} else {
_appLocale = Locale(langCode);
}
log(" ---- Fetched lang: " + _appLocale.toString());
}
getLocale(SharedPreferences prefs) {
String langCode = prefs.getString('language_code');
if (langCode == null) {
final String localName = Platform.localeName;
if (localName.endsWith("HU")) {
_appLocale = Locale('hu');
langCode = "hu";
} else {
_appLocale = Locale('en');
langCode = "en";
}
}
_appLocale = Locale(langCode);
log(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");
}
void changeLanguage(Locale type) async {
var prefs = await SharedPreferences.getInstance();
if (_appLocale == type) {
return;
}
if (type == Locale("hu")) {
_appLocale = Locale("hu");
await prefs.setString('language_code', 'hu');
await prefs.setString('countryCode', 'HU');
} else {
_appLocale = Locale("en");
await prefs.setString('language_code', 'en');
await prefs.setString('countryCode', 'US');
}
log(" ---- Stored lang: " + _appLocale.toString());
}
}
+80
View File
@@ -0,0 +1,80 @@
import 'dart:convert';
import 'dart:ui';
import 'package:aitrainer_app/service/logging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
class AppLocalizations with Logging {
Locale locale;
bool isTest;
AppLocalizations(this.locale, {this.isTest = false});
// Helper method to keep the code in the widgets concise
// Localizations are accessed using an InheritedWidget "of" syntax
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
// Static member to have a simple access to the delegate from the MaterialApp
static const LocalizationsDelegate<AppLocalizations> delegate = AppLocalizationsDelegate();
Map<String, String> _localizedStrings;
setLocale(Locale locale) {
this.locale = locale;
}
Future<bool> load() async {
// Load the language JSON file from the "lang" folder
log(" -- load language pieces " + locale.languageCode);
String jsonString = await rootBundle.loadString('i18n/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return true;
}
Future<AppLocalizations> loadTest(Locale locale) async {
return AppLocalizations(locale);
}
// This method will be called from every widget which needs a localized text
String translate(String key) {
if (isTest) return key;
String translated = _localizedStrings[key];
return translated != null ? translated : key;
}
}
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
final bool isTest;
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const AppLocalizationsDelegate({this.isTest = false});
@override
bool isSupported(Locale locale) {
// Include all of your supported language codes here
return ['en', 'hu'].contains(locale.languageCode);
}
@override
Future<AppLocalizations> load(Locale locale) async {
// AppLocalizations class is where the JSON loading actually runs
AppLocalizations localizations = new AppLocalizations(locale, isTest: this.isTest);
if (isTest) {
await localizations.loadTest(locale);
} else {
await localizations.load();
}
return localizations;
}
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
+1 -1
View File
@@ -1,6 +1,6 @@
import 'dart:convert';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
+9 -1
View File
@@ -36,7 +36,7 @@ enum TrackingEvent {
my_special_plan,
my_suggested_plan,
prediction,
search,
exercise_device,
customer_change,
settings_lang,
@@ -62,3 +62,11 @@ extension PropertyExt on PropertyEnum {
bool equalsTo(PropertyEnum event) => this.toString() == event.toString();
bool equalsStringTo(String event) => this.toString() == event;
}
enum SizesEnum { Weight, Height, Shoulder, Neck, Biceps, Chest, Belly, Hip, ThighTop, ThighMiddle, Knee, Calf, Ankle, Underarm, Lowerarm }
extension SizesExt on SizesEnum {
String toStr() => this.toString().split(".").last;
bool equalsTo(SizesEnum event) => this.toString() == event.toString();
bool equalsStringTo(String event) => this.toString() == event;
}
-231
View File
@@ -1,231 +0,0 @@
/*
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/product.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
class PlatformPurchaseApi with Logging {
static final PlatformPurchaseApi _singleton = PlatformPurchaseApi._internal();
bool _kAutoConsume = true;
final String _kConsumableId = 'consumable';
final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance;
bool _isAvailable = false;
List<ProductDetails> _products = [];
List<PurchaseDetails> _purchases = [];
List<String> _notFoundIds = [];
List<String> _consumables = [];
bool _purchasePending = false;
String _queryProductError;
StreamSubscription<List<PurchaseDetails>> _subscription;
final List<String> _productList = List();
List getProductList() => _productList;
factory PlatformPurchaseApi() {
return _singleton;
}
PlatformPurchaseApi._internal();
Future<void> close() async {
_subscription.cancel();
}
Future<void> initStoreInfo() async {
final bool isAvailable = await _connection.isAvailable();
if (!isAvailable) {
_isAvailable = isAvailable;
_products = [];
_purchases = [];
_notFoundIds = [];
_consumables = [];
_purchasePending = false;
log("Payment processor not available");
return;
}
getSubscriptions();
ProductDetailsResponse productDetailResponse = await _connection.queryProductDetails(_productList.toSet());
log("ProductDetailsResponse " + productDetailResponse.toString());
if (productDetailResponse.error != null) {
_queryProductError = productDetailResponse.error.message;
_isAvailable = isAvailable;
_products = productDetailResponse.productDetails;
_purchases = [];
_notFoundIds = productDetailResponse.notFoundIDs;
_consumables = [];
_purchasePending = false;
log("Payment processor not available");
return;
}
if (productDetailResponse.productDetails.isEmpty) {
_queryProductError = null;
_isAvailable = isAvailable;
_products = productDetailResponse.productDetails;
_purchases = [];
_notFoundIds = productDetailResponse.notFoundIDs;
_consumables = [];
_purchasePending = false;
return;
}
_products = productDetailResponse.productDetails;
_products.forEach((element) {
ProductDetails product = element as ProductDetails;
log("Product " + product.id + " " + product.price + " " + product.skuDetail.toString());
});
final QueryPurchaseDetailsResponse purchaseResponse = await _connection.queryPastPurchases();
if (purchaseResponse.error != null) {
// handle query past purchase error..
}
final List<PurchaseDetails> verifiedPurchases = [];
for (PurchaseDetails purchase in purchaseResponse.pastPurchases) {
if (await _verifyPurchase(purchase)) {
verifiedPurchases.add(purchase);
}
}
//TODO List<String> consumables = await ConsumableStore.load();
_isAvailable = isAvailable;
_products = productDetailResponse.productDetails;
_purchases = verifiedPurchases;
_notFoundIds = productDetailResponse.notFoundIDs;
//_consumables = consumables;
_purchasePending = false;
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPurchasePlatform() async {
if (_productList.length > 0) {
return;
}
log(' --- InappPurchase connection: $_connection');
log(" --- Init PurchasePlatform");
await this.initStoreInfo();
Stream purchaseUpdated = InAppPurchaseConnection.instance.purchaseUpdatedStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
_listenToPurchaseUpdated(purchaseDetailsList);
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// handle error here.
log("Error listen purchase updated " + error.toString());
});
}
void deliverProduct(PurchaseDetails purchaseDetails) async {
log("DeliverProduct");
// IMPORTANT!! Always verify a purchase purchase details before delivering the product.
if (purchaseDetails.productID == _kConsumableId) {
//TODO
//await ConsumableStore.save(purchaseDetails.purchaseID);
//List<String> consumables = await ConsumableStore.load();
_purchasePending = false;
//_consumables = consumables;
} else {
_purchases.add(purchaseDetails);
_purchasePending = false;
}
}
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) {
log("verifyPurchase");
// IMPORTANT!! Always verify a purchase before delivering the product.
// For the purpose of an example, we directly return true.
log("Verifying Purchase" + purchaseDetails.toString());
return Future<bool>.value(true);
}
void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {
// handle invalid purchase here if _verifyPurchase` failed.
log("Invalid Purchase" + purchaseDetails.toString());
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
if (purchaseDetails.status == PurchaseStatus.pending) {
//showPendingUI();
log("Purchase pending");
} else {
if (purchaseDetails.status == PurchaseStatus.error) {
//handleError(purchaseDetails.error);
} else if (purchaseDetails.status == PurchaseStatus.purchased) {
bool valid = await _verifyPurchase(purchaseDetails);
if (valid) {
deliverProduct(purchaseDetails);
} else {
_handleInvalidPurchase(purchaseDetails);
return;
}
}
if (Platform.isAndroid) {
if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) {
await InAppPurchaseConnection.instance.consumePurchase(purchaseDetails);
}
}
if (purchaseDetails.pendingCompletePurchase) {
await InAppPurchaseConnection.instance.completePurchase(purchaseDetails);
}
}
});
}
void getSubscriptions() {
Cache().products.forEach((element) {
Product product = element as Product;
if (Platform.isAndroid) {
if (product.productIdAndroid != null && product.productIdAndroid.isNotEmpty) {
_productList.add(product.productIdAndroid);
}
} else {
if (product.productIdIos != null && product.productIdIos.isNotEmpty) {
_productList.add(product.productIdIos);
}
}
});
_productList.forEach((element) {
print(element);
});
}
void purchase(Product product) {
if (product == null) {
throw Exception("No product to purchase");
}
String productId = Platform.isAndroid ? product.productIdAndroid : product.productIdIos;
ProductDetails productDetails;
_products.forEach((element) {
if (element.id == productId) {
productDetails = element;
log("product to purchase: " +
productDetails.id +
" title " +
productDetails.title +
" price " +
productDetails.price +
" period " +
productDetails.skuDetail.subscriptionPeriod);
}
});
final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails);
/* if (_isConsumable(productDetails)) {
InAppPurchaseConnection.instance.buyConsumable(purchaseParam: purchaseParam);
} else { */
InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);
//}
// From here the purchase flow will be handled by the underlying storefront.
// Updates will be delivered to the `InAppPurchaseConnection.instance.purchaseUpdatedStream`.
}
}
*/
+2 -1
View File
@@ -34,7 +34,8 @@ class RevenueCatPurchases with Logging {
Future<void> restore() async {
if (appUserId != null) {
try {
PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
//PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
PurchaserInfo purchaserInfo = await Purchases.getPurchaserInfo();
if (purchaserInfo != null &&
purchaserInfo.entitlements.all["wt_subscription"] != null &&
purchaserInfo.entitlements.all["wt_subscription"].isActive) {
+2 -6
View File
@@ -1,15 +1,11 @@
import 'dart:io';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/service/api.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/package_service.dart';
import 'package:aitrainer_app/service/product_service.dart';
import 'package:aitrainer_app/service/property_service.dart';
import 'package:aitrainer_app/util/purchases.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:devicelocale/devicelocale.dart';
import 'package:flutter/services.dart';
import 'package:package_info/package_info.dart';
+1 -1
View File
@@ -1,4 +1,4 @@
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:flutter/cupertino.dart';
mixin Trans {