Show option to download native app
This commit is contained in:
parent
61e9e3b1b5
commit
64ee9eaf95
|
|
@ -258,6 +258,12 @@ const kGatewayTypes = {
|
||||||
const String kNotificationChannelEmail = 'email';
|
const String kNotificationChannelEmail = 'email';
|
||||||
const String kNotificationChannelSlack = 'slack';
|
const String kNotificationChannelSlack = 'slack';
|
||||||
|
|
||||||
|
const String kPlatformWindows = 'Windows';
|
||||||
|
const String kPlatformLinux = 'Linux';
|
||||||
|
const String kPlatformMacOS = 'macOS';
|
||||||
|
const String kPlatformAndroid = 'Android';
|
||||||
|
const String kPlatformiPhone = 'iPhone';
|
||||||
|
|
||||||
const String kNotificationsAll = 'all_notifications';
|
const String kNotificationsAll = 'all_notifications';
|
||||||
const String kNotificationsAllUser = 'all_user_notifications';
|
const String kNotificationsAllUser = 'all_user_notifications';
|
||||||
const String kNotificationsPaymentSuccess = 'payment_success';
|
const String kNotificationsPaymentSuccess = 'payment_success';
|
||||||
|
|
|
||||||
|
|
@ -50,30 +50,24 @@ import 'package:invoiceninja_flutter/ui/credit/edit/credit_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/design/edit/design_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/design/edit/design_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/product/edit/product_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/product/edit/product_edit_vm.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
import 'package:invoiceninja_flutter/redux/recurring_expense/recurring_expense_state.dart';
|
import 'package:invoiceninja_flutter/redux/recurring_expense/recurring_expense_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/recurring_expense/edit/recurring_expense_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/recurring_expense/edit/recurring_expense_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/recurring_expense/recurring_expense_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/recurring_expense/recurring_expense_selectors.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/subscription/subscription_state.dart';
|
import 'package:invoiceninja_flutter/redux/subscription/subscription_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/recurring_expense/recurring_expense_screen.dart';
|
import 'package:invoiceninja_flutter/ui/recurring_expense/recurring_expense_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/subscription/edit/subscription_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/subscription/edit/subscription_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/subscription/subscription_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/subscription/subscription_selectors.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/task_status/task_status_state.dart';
|
import 'package:invoiceninja_flutter/redux/task_status/task_status_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/recurring_invoice/recurring_invoice_screen.dart';
|
import 'package:invoiceninja_flutter/ui/recurring_invoice/recurring_invoice_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/task_status/edit/task_status_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/task_status/edit/task_status_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/task_status/task_status_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/task_status/task_status_selectors.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/expense_category/expense_category_state.dart';
|
import 'package:invoiceninja_flutter/redux/expense_category/expense_category_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/expense_category/edit/expense_category_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/expense_category/edit/expense_category_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/expense_category/expense_category_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/expense_category/expense_category_selectors.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_state.dart';
|
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/recurring_invoice/edit/recurring_invoice_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/recurring_invoice/edit/recurring_invoice_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_selectors.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja_flutter/redux/webhook/webhook_state.dart';
|
import 'package:invoiceninja_flutter/redux/webhook/webhook_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/webhook/edit/webhook_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/webhook/edit/webhook_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/webhook/webhook_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/webhook/webhook_selectors.dart';
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,7 @@ class _LoginState extends State<LoginView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
|
final platform = getNativePlatform();
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
final state = viewModel.state;
|
final state = viewModel.state;
|
||||||
|
|
||||||
|
|
@ -676,9 +677,15 @@ class _LoginState extends State<LoginView> {
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!_recoverPassword && !_isSelfHosted)
|
if (!_recoverPassword && (!_isSelfHosted || kIsWeb))
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () => launch(kStatusCheckUrl),
|
onTap: () {
|
||||||
|
if (platform.isNotEmpty) {
|
||||||
|
launch(getNativeAppUrl(platform));
|
||||||
|
} else {
|
||||||
|
launch(kStatusCheckUrl);
|
||||||
|
}
|
||||||
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 25, top: 12, right: 20, bottom: 12),
|
left: 25, top: 12, right: 20, bottom: 12),
|
||||||
|
|
@ -686,9 +693,15 @@ class _LoginState extends State<LoginView> {
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.security, size: 16),
|
Icon(
|
||||||
|
platform.isEmpty
|
||||||
|
? Icons.security
|
||||||
|
: getNativeAppIcon(platform),
|
||||||
|
size: 16),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Text(localization.checkStatus)
|
Text(platform.isEmpty
|
||||||
|
? localization.checkStatus
|
||||||
|
: '$platform ${localization.app}')
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
// STARTER: lang key - do not remove comment
|
// STARTER: lang key - do not remove comment
|
||||||
|
'app': 'App',
|
||||||
|
'for_best_performance': 'For the best performance download the :app app',
|
||||||
'gross_line_total': 'Gross Line Total',
|
'gross_line_total': 'Gross Line Total',
|
||||||
'bulk_email_invoice': 'Email Invoice',
|
'bulk_email_invoice': 'Email Invoice',
|
||||||
'bulk_email_quote': 'Email Quote',
|
'bulk_email_quote': 'Email Quote',
|
||||||
|
|
@ -62623,6 +62625,13 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
_localizedValues[localeCode]['gross_line_total'] ??
|
_localizedValues[localeCode]['gross_line_total'] ??
|
||||||
_localizedValues['en']['gross_line_total'];
|
_localizedValues['en']['gross_line_total'];
|
||||||
|
|
||||||
|
String get forBestPerformance =>
|
||||||
|
_localizedValues[localeCode]['for_best_performance'] ??
|
||||||
|
_localizedValues['en']['for_best_performance'];
|
||||||
|
|
||||||
|
String get app =>
|
||||||
|
_localizedValues[localeCode]['app'] ?? _localizedValues['en']['app'];
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
|
||||||
String lookup(String key) {
|
String lookup(String key) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/web_stub.dart'
|
||||||
|
if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';
|
||||||
|
|
||||||
bool isDesktopOS() => isMacOS() || isWindows() || isLinux();
|
bool isDesktopOS() => isMacOS() || isWindows() || isLinux();
|
||||||
|
|
||||||
|
|
@ -78,6 +81,69 @@ String getPdfRequirements(BuildContext context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getNativePlatform() {
|
||||||
|
String userAgent = WebUtils.getHtmlValue('user-agent') ?? '';
|
||||||
|
userAgent = userAgent.toLowerCase();
|
||||||
|
|
||||||
|
if (userAgent.contains('ipad') ||
|
||||||
|
userAgent.contains('ipod') ||
|
||||||
|
userAgent.contains('iphone')) {
|
||||||
|
return kPlatformiPhone;
|
||||||
|
} else if (userAgent.contains('android')) {
|
||||||
|
return kPlatformAndroid;
|
||||||
|
} else if (userAgent.contains('win')) {
|
||||||
|
return kPlatformWindows;
|
||||||
|
} else if (userAgent.contains('mac')) {
|
||||||
|
return kPlatformMacOS;
|
||||||
|
} else if (userAgent.contains('linux')) {
|
||||||
|
return kPlatformLinux;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNativeAppUrl(String platform) {
|
||||||
|
if (!kIsWeb) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (platform) {
|
||||||
|
case kPlatformAndroid:
|
||||||
|
return kGoogleStoreUrl;
|
||||||
|
case kPlatformiPhone:
|
||||||
|
return kAppleStoreUrl;
|
||||||
|
case kPlatformWindows:
|
||||||
|
return kWindowsUrl;
|
||||||
|
case kPlatformMacOS:
|
||||||
|
return kMacOSUrl;
|
||||||
|
case kPlatformLinux:
|
||||||
|
return kLinuxUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData getNativeAppIcon(String platform) {
|
||||||
|
if (!kIsWeb) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (platform) {
|
||||||
|
case kPlatformAndroid:
|
||||||
|
return Icons.android;
|
||||||
|
case kPlatformiPhone:
|
||||||
|
return MdiIcons.apple;
|
||||||
|
case kPlatformWindows:
|
||||||
|
return MdiIcons.microsoft;
|
||||||
|
case kPlatformMacOS:
|
||||||
|
return MdiIcons.apple;
|
||||||
|
case kPlatformLinux:
|
||||||
|
return MdiIcons.linux;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
String getPlatform(BuildContext context) =>
|
String getPlatform(BuildContext context) =>
|
||||||
Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android';
|
Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html data-report-errors="1" data-rc="" data-user-agent="">
|
||||||
<head>
|
<head>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue