IAP
This commit is contained in:
parent
595bba9f75
commit
89f3f314a5
|
|
@ -197,15 +197,18 @@ abstract class CompanyEntity
|
||||||
@nullable
|
@nullable
|
||||||
@BuiltValueField(wireName: 'task_statuses')
|
@BuiltValueField(wireName: 'task_statuses')
|
||||||
BuiltList<TaskStatusEntity> get taskStatuses;
|
BuiltList<TaskStatusEntity> get taskStatuses;
|
||||||
|
|
||||||
BuiltMap<int, TaskStatusEntity> get taskStatusMap;
|
BuiltMap<int, TaskStatusEntity> get taskStatusMap;
|
||||||
|
|
||||||
@nullable
|
@nullable
|
||||||
@BuiltValueField(wireName: 'expense_categories')
|
@BuiltValueField(wireName: 'expense_categories')
|
||||||
BuiltList<ExpenseCategoryEntity> get expenseCategories;
|
BuiltList<ExpenseCategoryEntity> get expenseCategories;
|
||||||
|
|
||||||
BuiltMap<int, ExpenseCategoryEntity> get expenseCategoryMap;
|
BuiltMap<int, ExpenseCategoryEntity> get expenseCategoryMap;
|
||||||
|
|
||||||
@BuiltValueField(wireName: 'users')
|
@BuiltValueField(wireName: 'users')
|
||||||
BuiltList<UserEntity> get users;
|
BuiltList<UserEntity> get users;
|
||||||
|
|
||||||
BuiltMap<int, UserEntity> get userMap;
|
BuiltMap<int, UserEntity> get userMap;
|
||||||
|
|
||||||
UserEntity get user;
|
UserEntity get user;
|
||||||
|
|
@ -316,9 +319,13 @@ abstract class CompanyEntity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isSelfHost => appUrl != kAppUrl;
|
bool get isSelfHost =>
|
||||||
|
appUrl != null && appUrl.isNotEmpty && appUrl != kAppUrl;
|
||||||
|
|
||||||
bool get isProPlan => isSelfHost || plan == kPlanPro;
|
bool get isHosted => !isSelfHost;
|
||||||
|
|
||||||
|
bool get isProPlan =>
|
||||||
|
isSelfHost || plan == kPlanPro;
|
||||||
|
|
||||||
bool get isEnterprisePlan => isProPlan || plan == kPlanEnterprise;
|
bool get isEnterprisePlan => isProPlan || plan == kPlanEnterprise;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,12 +113,14 @@ void main({bool isTesting = false}) async {
|
||||||
runZoned<Future<void>>(() async {
|
runZoned<Future<void>>(() async {
|
||||||
runApp(InvoiceNinjaApp(store: store));
|
runApp(InvoiceNinjaApp(store: store));
|
||||||
}, onError: (dynamic error, dynamic stackTrace) {
|
}, onError: (dynamic error, dynamic stackTrace) {
|
||||||
_reportError(error, stackTrace);
|
if (store.state.isHosted) {
|
||||||
|
_reportError(error, stackTrace);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FlutterError.onError = (FlutterErrorDetails details) {
|
FlutterError.onError = (FlutterErrorDetails details) {
|
||||||
if (isInDebugMode) {
|
if (isInDebugMode || store.state.isSelfHosted) {
|
||||||
FlutterError.dumpErrorToConsole(details);
|
FlutterError.dumpErrorToConsole(details);
|
||||||
} else {
|
} else {
|
||||||
Zone.current.handleUncaughtError(details.exception, details.stack);
|
Zone.current.handleUncaughtError(details.exception, details.stack);
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,10 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isHosted => authState.isHosted ?? false;
|
||||||
|
|
||||||
|
bool get isSelfHosted => !isHosted;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'URL: ${authState.url}';
|
return 'URL: ${authState.url}';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:built_value/built_value.dart';
|
import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
|
|
||||||
part 'auth_state.g.dart';
|
part 'auth_state.g.dart';
|
||||||
|
|
||||||
|
|
@ -14,18 +15,29 @@ abstract class AuthState implements Built<AuthState, AuthStateBuilder> {
|
||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthState._();
|
AuthState._();
|
||||||
|
|
||||||
String get email;
|
String get email;
|
||||||
|
|
||||||
String get password;
|
String get password;
|
||||||
|
|
||||||
String get url;
|
String get url;
|
||||||
|
|
||||||
String get secret;
|
String get secret;
|
||||||
|
|
||||||
bool get isInitialized;
|
bool get isInitialized;
|
||||||
|
|
||||||
bool get isAuthenticated;
|
bool get isAuthenticated;
|
||||||
|
|
||||||
@nullable
|
@nullable
|
||||||
String get error;
|
String get error;
|
||||||
|
|
||||||
|
bool get isHosted =>
|
||||||
|
isAuthenticated && (url == null || url.isEmpty || url == kAppUrl);
|
||||||
|
|
||||||
|
bool get isSelfHost => isAuthenticated && !isHosted;
|
||||||
|
|
||||||
//factory AuthState([void updates(AuthStateBuilder b)]) = _$AuthState;
|
//factory AuthState([void updates(AuthStateBuilder b)]) = _$AuthState;
|
||||||
static Serializer<AuthState> get serializer => _$authStateSerializer;
|
static Serializer<AuthState> get serializer => _$authStateSerializer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ String localeSelector(AppState state) {
|
||||||
'en';
|
'en';
|
||||||
|
|
||||||
// https://github.com/flutter/flutter/issues/32090
|
// https://github.com/flutter/flutter/issues/32090
|
||||||
if (locale == 'mk_MK') {
|
if (locale == 'mk_MK' || locale == 'sq') {
|
||||||
return 'en';
|
return 'en';
|
||||||
} else {
|
} else {
|
||||||
return locale;
|
return locale;
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,7 @@ class SidebarFooter extends StatelessWidget {
|
||||||
icon: Icon(Icons.info_outline),
|
icon: Icon(Icons.info_outline),
|
||||||
onPressed: () => showAbout(),
|
onPressed: () => showAbout(),
|
||||||
),
|
),
|
||||||
if (isHosted(context) && !isProAccount(context)) ...[
|
if (isHosted(context) && !isPaidAccount(context)) ...[
|
||||||
Spacer(),
|
Spacer(),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text(localization.upgrade),
|
child: Text(localization.upgrade),
|
||||||
|
|
|
||||||
|
|
@ -5,33 +5,24 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
||||||
|
|
||||||
bool isAndroid(BuildContext context) =>
|
bool isAndroid(BuildContext context) =>
|
||||||
Theme
|
Theme.of(context).platform == TargetPlatform.android;
|
||||||
.of(context)
|
|
||||||
.platform == TargetPlatform.android;
|
|
||||||
|
|
||||||
String getMapURL(BuildContext context) =>
|
String getMapURL(BuildContext context) => isAndroid(context)
|
||||||
isAndroid(context)
|
? 'https://maps.google.com/?q='
|
||||||
? 'https://maps.google.com/?q='
|
: 'http://maps.apple.com/?address=';
|
||||||
: 'http://maps.apple.com/?address=';
|
|
||||||
|
|
||||||
String getLegacyAppURL(BuildContext context) =>
|
String getLegacyAppURL(BuildContext context) => isAndroid(context)
|
||||||
isAndroid(context)
|
? 'https://play.google.com/store/apps/details?id=com.invoiceninja.invoiceninja'
|
||||||
? 'https://play.google.com/store/apps/details?id=com.invoiceninja.invoiceninja'
|
: 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1220337560&mt=8';
|
||||||
: 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1220337560&mt=8';
|
|
||||||
|
|
||||||
String getPlatform(BuildContext context) =>
|
String getPlatform(BuildContext context) =>
|
||||||
Theme
|
Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android';
|
||||||
.of(context)
|
|
||||||
.platform == TargetPlatform.iOS ? 'ios' : 'android';
|
|
||||||
|
|
||||||
String getAppURL(BuildContext context) =>
|
String getAppURL(BuildContext context) =>
|
||||||
isAndroid(context) ? kGoogleStoreUrl : kAppleStoreUrl;
|
isAndroid(context) ? kGoogleStoreUrl : kAppleStoreUrl;
|
||||||
|
|
||||||
AppLayout calculateLayout(BuildContext context) {
|
AppLayout calculateLayout(BuildContext context) {
|
||||||
final size = MediaQuery
|
final size = MediaQuery.of(context).size.shortestSide;
|
||||||
.of(context)
|
|
||||||
.size
|
|
||||||
.shortestSide;
|
|
||||||
if (size < kMobileLayoutWidth) {
|
if (size < kMobileLayoutWidth) {
|
||||||
return AppLayout.mobile;
|
return AppLayout.mobile;
|
||||||
} else if (size > kTabletLayoutWidth) {
|
} else if (size > kTabletLayoutWidth) {
|
||||||
|
|
@ -42,12 +33,8 @@ AppLayout calculateLayout(BuildContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AppLayout getLayout(BuildContext context) =>
|
AppLayout getLayout(BuildContext context) =>
|
||||||
StoreProvider
|
StoreProvider.of<AppState>(context).state.uiState.layout ??
|
||||||
.of<AppState>(context)
|
AppLayout.mobile;
|
||||||
.state
|
|
||||||
.uiState
|
|
||||||
.layout ??
|
|
||||||
AppLayout.mobile;
|
|
||||||
|
|
||||||
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;
|
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;
|
||||||
|
|
||||||
|
|
@ -56,22 +43,16 @@ bool isTablet(BuildContext context) => getLayout(context) == AppLayout.tablet;
|
||||||
bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop;
|
bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop;
|
||||||
|
|
||||||
bool isDarkMode(BuildContext context) =>
|
bool isDarkMode(BuildContext context) =>
|
||||||
StoreProvider
|
StoreProvider.of<AppState>(context).state.uiState.enableDarkMode;
|
||||||
.of<AppState>(context)
|
|
||||||
.state
|
|
||||||
.uiState
|
|
||||||
.enableDarkMode;
|
|
||||||
|
|
||||||
bool isSelfHosted(BuildContext context) =>
|
bool isSelfHosted(BuildContext context) =>
|
||||||
StoreProvider
|
StoreProvider.of<AppState>(context).state.isSelfHosted;
|
||||||
.of<AppState>(context)
|
|
||||||
.state.selectedCompany.isSelfHost;
|
|
||||||
|
|
||||||
bool isHosted(BuildContext context) => !isSelfHosted(context);
|
bool isHosted(BuildContext context) =>
|
||||||
|
StoreProvider.of<AppState>(context).state.isHosted;
|
||||||
|
|
||||||
bool isProAccount(BuildContext context) =>
|
bool isPaidAccount(BuildContext context) {
|
||||||
isSelfHosted(context) || StoreProvider
|
final company = StoreProvider.of<AppState>(context).state.selectedCompany;
|
||||||
.of<AppState>(context)
|
|
||||||
.state
|
return isSelfHosted(context) || company.isProPlan || company.isEnterprisePlan;
|
||||||
.selectedCompany
|
}
|
||||||
.isProPlan;
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue