Add CTA to Chrome task extension
This commit is contained in:
parent
2fb7945f23
commit
267fe96644
|
|
@ -53,6 +53,11 @@ const String kFacebookUrl = 'https://www.facebook.com/invoiceninja';
|
||||||
const String kYouTubeUrl =
|
const String kYouTubeUrl =
|
||||||
'https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA/videos';
|
'https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA/videos';
|
||||||
|
|
||||||
|
const String kTaskExtensionUrl =
|
||||||
|
'https://chromewebstore.google.com/detail/invoice-ninja-tasks/dlfcbfdpemfnjbjlladogijcchfmmaaf';
|
||||||
|
const String kTaskExtensionYouTubeUrl =
|
||||||
|
'https://www.youtube.com/watch?v=UL0OklMJTEA&ab_channel=InvoiceNinja';
|
||||||
|
|
||||||
const String kAppleOAuthClientId = 'com.invoiceninja.client';
|
const String kAppleOAuthClientId = 'com.invoiceninja.client';
|
||||||
const String kAppleOAuthRedirectUrl = 'https://invoicing.co/auth/apple';
|
const String kAppleOAuthRedirectUrl = 'https://invoicing.co/auth/apple';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,8 @@ class DismissOneYearReviewAppPermanently implements PersistUI, PersistPrefs {}
|
||||||
|
|
||||||
class DismissTwoYearReviewAppPermanently implements PersistUI, PersistPrefs {}
|
class DismissTwoYearReviewAppPermanently implements PersistUI, PersistPrefs {}
|
||||||
|
|
||||||
|
class DismissTaskExtensionBanner implements PersistUI, PersistPrefs {}
|
||||||
|
|
||||||
class ViewMainScreen {
|
class ViewMainScreen {
|
||||||
ViewMainScreen({this.addDelay = false});
|
ViewMainScreen({this.addDelay = false});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ PrefState prefReducer(
|
||||||
historySidebarReducer(state.historySidebarMode, action)
|
historySidebarReducer(state.historySidebarMode, action)
|
||||||
..hideDesktopWarning =
|
..hideDesktopWarning =
|
||||||
hideDesktopWarningReducer(state.hideDesktopWarning, action)
|
hideDesktopWarningReducer(state.hideDesktopWarning, action)
|
||||||
|
..hideTaskExtensionBanner =
|
||||||
|
hideTaskExtensionBannerReducer(state.hideTaskExtensionBanner, action)
|
||||||
..hideGatewayWarning =
|
..hideGatewayWarning =
|
||||||
hideGatewayWarningReducer(state.hideGatewayWarning, action)
|
hideGatewayWarningReducer(state.hideGatewayWarning, action)
|
||||||
..hideReviewApp = hideReviewAppReducer(state.hideReviewApp, action)
|
..hideReviewApp = hideReviewAppReducer(state.hideReviewApp, action)
|
||||||
|
|
@ -260,6 +262,12 @@ Reducer<bool> hideDesktopWarningReducer = combineReducers([
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Reducer<bool> hideTaskExtensionBannerReducer = combineReducers([
|
||||||
|
TypedReducer<bool, DismissTaskExtensionBanner>((filter, action) {
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
Reducer<bool> hideGatewayWarningReducer = combineReducers([
|
Reducer<bool> hideGatewayWarningReducer = combineReducers([
|
||||||
TypedReducer<bool, DismissGatewayWarningPermanently>((filter, action) {
|
TypedReducer<bool, DismissGatewayWarningPermanently>((filter, action) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
|
||||||
hideReviewApp: false,
|
hideReviewApp: false,
|
||||||
hideOneYearReviewApp: false,
|
hideOneYearReviewApp: false,
|
||||||
hideTwoYearReviewApp: false,
|
hideTwoYearReviewApp: false,
|
||||||
|
hideTaskExtensionBanner: false,
|
||||||
showKanban: false,
|
showKanban: false,
|
||||||
showPdfPreview: true,
|
showPdfPreview: true,
|
||||||
showPdfPreviewSideBySide: false,
|
showPdfPreviewSideBySide: false,
|
||||||
|
|
@ -170,6 +171,8 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
|
||||||
|
|
||||||
bool get hideTwoYearReviewApp;
|
bool get hideTwoYearReviewApp;
|
||||||
|
|
||||||
|
bool get hideTaskExtensionBanner;
|
||||||
|
|
||||||
bool get editAfterSaving;
|
bool get editAfterSaving;
|
||||||
|
|
||||||
bool get enableNativeBrowser;
|
bool get enableNativeBrowser;
|
||||||
|
|
@ -288,7 +291,8 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
|
||||||
..colorTheme = kColorThemeLight
|
..colorTheme = kColorThemeLight
|
||||||
..darkColorTheme = kColorThemeDark
|
..darkColorTheme = kColorThemeDark
|
||||||
..enableDarkModeSystem = false
|
..enableDarkModeSystem = false
|
||||||
..donwloadsFolder = '';
|
..donwloadsFolder = ''
|
||||||
|
..hideTaskExtensionBanner = false;
|
||||||
|
|
||||||
static Serializer<PrefState> get serializer => _$prefStateSerializer;
|
static Serializer<PrefState> get serializer => _$prefStateSerializer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,9 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
|
||||||
'hideTwoYearReviewApp',
|
'hideTwoYearReviewApp',
|
||||||
serializers.serialize(object.hideTwoYearReviewApp,
|
serializers.serialize(object.hideTwoYearReviewApp,
|
||||||
specifiedType: const FullType(bool)),
|
specifiedType: const FullType(bool)),
|
||||||
|
'hideTaskExtensionBanner',
|
||||||
|
serializers.serialize(object.hideTaskExtensionBanner,
|
||||||
|
specifiedType: const FullType(bool)),
|
||||||
'editAfterSaving',
|
'editAfterSaving',
|
||||||
serializers.serialize(object.editAfterSaving,
|
serializers.serialize(object.editAfterSaving,
|
||||||
specifiedType: const FullType(bool)),
|
specifiedType: const FullType(bool)),
|
||||||
|
|
@ -402,6 +405,10 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
|
||||||
result.hideTwoYearReviewApp = serializers.deserialize(value,
|
result.hideTwoYearReviewApp = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(bool))! as bool;
|
specifiedType: const FullType(bool))! as bool;
|
||||||
break;
|
break;
|
||||||
|
case 'hideTaskExtensionBanner':
|
||||||
|
result.hideTaskExtensionBanner = serializers.deserialize(value,
|
||||||
|
specifiedType: const FullType(bool))! as bool;
|
||||||
|
break;
|
||||||
case 'editAfterSaving':
|
case 'editAfterSaving':
|
||||||
result.editAfterSaving = serializers.deserialize(value,
|
result.editAfterSaving = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(bool))! as bool;
|
specifiedType: const FullType(bool))! as bool;
|
||||||
|
|
@ -742,6 +749,8 @@ class _$PrefState extends PrefState {
|
||||||
@override
|
@override
|
||||||
final bool hideTwoYearReviewApp;
|
final bool hideTwoYearReviewApp;
|
||||||
@override
|
@override
|
||||||
|
final bool hideTaskExtensionBanner;
|
||||||
|
@override
|
||||||
final bool editAfterSaving;
|
final bool editAfterSaving;
|
||||||
@override
|
@override
|
||||||
final bool enableNativeBrowser;
|
final bool enableNativeBrowser;
|
||||||
|
|
@ -792,6 +801,7 @@ class _$PrefState extends PrefState {
|
||||||
required this.hideReviewApp,
|
required this.hideReviewApp,
|
||||||
required this.hideOneYearReviewApp,
|
required this.hideOneYearReviewApp,
|
||||||
required this.hideTwoYearReviewApp,
|
required this.hideTwoYearReviewApp,
|
||||||
|
required this.hideTaskExtensionBanner,
|
||||||
required this.editAfterSaving,
|
required this.editAfterSaving,
|
||||||
required this.enableNativeBrowser,
|
required this.enableNativeBrowser,
|
||||||
required this.textScaleFactor,
|
required this.textScaleFactor,
|
||||||
|
|
@ -865,6 +875,8 @@ class _$PrefState extends PrefState {
|
||||||
hideOneYearReviewApp, r'PrefState', 'hideOneYearReviewApp');
|
hideOneYearReviewApp, r'PrefState', 'hideOneYearReviewApp');
|
||||||
BuiltValueNullFieldError.checkNotNull(
|
BuiltValueNullFieldError.checkNotNull(
|
||||||
hideTwoYearReviewApp, r'PrefState', 'hideTwoYearReviewApp');
|
hideTwoYearReviewApp, r'PrefState', 'hideTwoYearReviewApp');
|
||||||
|
BuiltValueNullFieldError.checkNotNull(
|
||||||
|
hideTaskExtensionBanner, r'PrefState', 'hideTaskExtensionBanner');
|
||||||
BuiltValueNullFieldError.checkNotNull(
|
BuiltValueNullFieldError.checkNotNull(
|
||||||
editAfterSaving, r'PrefState', 'editAfterSaving');
|
editAfterSaving, r'PrefState', 'editAfterSaving');
|
||||||
BuiltValueNullFieldError.checkNotNull(
|
BuiltValueNullFieldError.checkNotNull(
|
||||||
|
|
@ -924,6 +936,7 @@ class _$PrefState extends PrefState {
|
||||||
hideReviewApp == other.hideReviewApp &&
|
hideReviewApp == other.hideReviewApp &&
|
||||||
hideOneYearReviewApp == other.hideOneYearReviewApp &&
|
hideOneYearReviewApp == other.hideOneYearReviewApp &&
|
||||||
hideTwoYearReviewApp == other.hideTwoYearReviewApp &&
|
hideTwoYearReviewApp == other.hideTwoYearReviewApp &&
|
||||||
|
hideTaskExtensionBanner == other.hideTaskExtensionBanner &&
|
||||||
editAfterSaving == other.editAfterSaving &&
|
editAfterSaving == other.editAfterSaving &&
|
||||||
enableNativeBrowser == other.enableNativeBrowser &&
|
enableNativeBrowser == other.enableNativeBrowser &&
|
||||||
textScaleFactor == other.textScaleFactor &&
|
textScaleFactor == other.textScaleFactor &&
|
||||||
|
|
@ -971,6 +984,7 @@ class _$PrefState extends PrefState {
|
||||||
_$hash = $jc(_$hash, hideReviewApp.hashCode);
|
_$hash = $jc(_$hash, hideReviewApp.hashCode);
|
||||||
_$hash = $jc(_$hash, hideOneYearReviewApp.hashCode);
|
_$hash = $jc(_$hash, hideOneYearReviewApp.hashCode);
|
||||||
_$hash = $jc(_$hash, hideTwoYearReviewApp.hashCode);
|
_$hash = $jc(_$hash, hideTwoYearReviewApp.hashCode);
|
||||||
|
_$hash = $jc(_$hash, hideTaskExtensionBanner.hashCode);
|
||||||
_$hash = $jc(_$hash, editAfterSaving.hashCode);
|
_$hash = $jc(_$hash, editAfterSaving.hashCode);
|
||||||
_$hash = $jc(_$hash, enableNativeBrowser.hashCode);
|
_$hash = $jc(_$hash, enableNativeBrowser.hashCode);
|
||||||
_$hash = $jc(_$hash, textScaleFactor.hashCode);
|
_$hash = $jc(_$hash, textScaleFactor.hashCode);
|
||||||
|
|
@ -1018,6 +1032,7 @@ class _$PrefState extends PrefState {
|
||||||
..add('hideReviewApp', hideReviewApp)
|
..add('hideReviewApp', hideReviewApp)
|
||||||
..add('hideOneYearReviewApp', hideOneYearReviewApp)
|
..add('hideOneYearReviewApp', hideOneYearReviewApp)
|
||||||
..add('hideTwoYearReviewApp', hideTwoYearReviewApp)
|
..add('hideTwoYearReviewApp', hideTwoYearReviewApp)
|
||||||
|
..add('hideTaskExtensionBanner', hideTaskExtensionBanner)
|
||||||
..add('editAfterSaving', editAfterSaving)
|
..add('editAfterSaving', editAfterSaving)
|
||||||
..add('enableNativeBrowser', enableNativeBrowser)
|
..add('enableNativeBrowser', enableNativeBrowser)
|
||||||
..add('textScaleFactor', textScaleFactor)
|
..add('textScaleFactor', textScaleFactor)
|
||||||
|
|
@ -1199,6 +1214,11 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
|
||||||
set hideTwoYearReviewApp(bool? hideTwoYearReviewApp) =>
|
set hideTwoYearReviewApp(bool? hideTwoYearReviewApp) =>
|
||||||
_$this._hideTwoYearReviewApp = hideTwoYearReviewApp;
|
_$this._hideTwoYearReviewApp = hideTwoYearReviewApp;
|
||||||
|
|
||||||
|
bool? _hideTaskExtensionBanner;
|
||||||
|
bool? get hideTaskExtensionBanner => _$this._hideTaskExtensionBanner;
|
||||||
|
set hideTaskExtensionBanner(bool? hideTaskExtensionBanner) =>
|
||||||
|
_$this._hideTaskExtensionBanner = hideTaskExtensionBanner;
|
||||||
|
|
||||||
bool? _editAfterSaving;
|
bool? _editAfterSaving;
|
||||||
bool? get editAfterSaving => _$this._editAfterSaving;
|
bool? get editAfterSaving => _$this._editAfterSaving;
|
||||||
set editAfterSaving(bool? editAfterSaving) =>
|
set editAfterSaving(bool? editAfterSaving) =>
|
||||||
|
|
@ -1272,6 +1292,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
|
||||||
_hideReviewApp = $v.hideReviewApp;
|
_hideReviewApp = $v.hideReviewApp;
|
||||||
_hideOneYearReviewApp = $v.hideOneYearReviewApp;
|
_hideOneYearReviewApp = $v.hideOneYearReviewApp;
|
||||||
_hideTwoYearReviewApp = $v.hideTwoYearReviewApp;
|
_hideTwoYearReviewApp = $v.hideTwoYearReviewApp;
|
||||||
|
_hideTaskExtensionBanner = $v.hideTaskExtensionBanner;
|
||||||
_editAfterSaving = $v.editAfterSaving;
|
_editAfterSaving = $v.editAfterSaving;
|
||||||
_enableNativeBrowser = $v.enableNativeBrowser;
|
_enableNativeBrowser = $v.enableNativeBrowser;
|
||||||
_textScaleFactor = $v.textScaleFactor;
|
_textScaleFactor = $v.textScaleFactor;
|
||||||
|
|
@ -1344,6 +1365,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
|
||||||
hideReviewApp: BuiltValueNullFieldError.checkNotNull(hideReviewApp, r'PrefState', 'hideReviewApp'),
|
hideReviewApp: BuiltValueNullFieldError.checkNotNull(hideReviewApp, r'PrefState', 'hideReviewApp'),
|
||||||
hideOneYearReviewApp: BuiltValueNullFieldError.checkNotNull(hideOneYearReviewApp, r'PrefState', 'hideOneYearReviewApp'),
|
hideOneYearReviewApp: BuiltValueNullFieldError.checkNotNull(hideOneYearReviewApp, r'PrefState', 'hideOneYearReviewApp'),
|
||||||
hideTwoYearReviewApp: BuiltValueNullFieldError.checkNotNull(hideTwoYearReviewApp, r'PrefState', 'hideTwoYearReviewApp'),
|
hideTwoYearReviewApp: BuiltValueNullFieldError.checkNotNull(hideTwoYearReviewApp, r'PrefState', 'hideTwoYearReviewApp'),
|
||||||
|
hideTaskExtensionBanner: BuiltValueNullFieldError.checkNotNull(hideTaskExtensionBanner, r'PrefState', 'hideTaskExtensionBanner'),
|
||||||
editAfterSaving: BuiltValueNullFieldError.checkNotNull(editAfterSaving, r'PrefState', 'editAfterSaving'),
|
editAfterSaving: BuiltValueNullFieldError.checkNotNull(editAfterSaving, r'PrefState', 'editAfterSaving'),
|
||||||
enableNativeBrowser: BuiltValueNullFieldError.checkNotNull(enableNativeBrowser, r'PrefState', 'enableNativeBrowser'),
|
enableNativeBrowser: BuiltValueNullFieldError.checkNotNull(enableNativeBrowser, r'PrefState', 'enableNativeBrowser'),
|
||||||
textScaleFactor: BuiltValueNullFieldError.checkNotNull(textScaleFactor, r'PrefState', 'textScaleFactor'),
|
textScaleFactor: BuiltValueNullFieldError.checkNotNull(textScaleFactor, r'PrefState', 'textScaleFactor'),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
// Flutter imports:
|
// Flutter imports:
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
// Package imports:
|
// Package imports:
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.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/ui/app/icon_text.dart';
|
||||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
|
|
@ -23,6 +25,7 @@ import 'package:invoiceninja_flutter/ui/task/task_screen_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/icons.dart';
|
import 'package:invoiceninja_flutter/utils/icons.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class TaskScreen extends StatelessWidget {
|
class TaskScreen extends StatelessWidget {
|
||||||
const TaskScreen({
|
const TaskScreen({
|
||||||
|
|
@ -40,18 +43,18 @@ class TaskScreen extends StatelessWidget {
|
||||||
final state = store.state;
|
final state = store.state;
|
||||||
final company = store.state.company;
|
final company = store.state.company;
|
||||||
final userCompany = store.state.userCompany;
|
final userCompany = store.state.userCompany;
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context)!;
|
||||||
final statuses = [
|
final statuses = [
|
||||||
TaskStatusEntity().rebuild((b) => b
|
TaskStatusEntity().rebuild((b) => b
|
||||||
..id = kTaskStatusLogged
|
..id = kTaskStatusLogged
|
||||||
..name = localization!.logged),
|
..name = localization.logged),
|
||||||
TaskStatusEntity().rebuild((b) => b
|
TaskStatusEntity().rebuild((b) => b
|
||||||
..id = kTaskStatusRunning
|
..id = kTaskStatusRunning
|
||||||
..name = localization!.running),
|
..name = localization.running),
|
||||||
if (!state.prefState.showKanban)
|
if (!state.prefState.showKanban)
|
||||||
TaskStatusEntity().rebuild((b) => b
|
TaskStatusEntity().rebuild((b) => b
|
||||||
..id = kTaskStatusInvoiced
|
..id = kTaskStatusInvoiced
|
||||||
..name = localization!.invoiced),
|
..name = localization.invoiced),
|
||||||
for (var statusId in memoizedSortedActiveTaskStatusIds(
|
for (var statusId in memoizedSortedActiveTaskStatusIds(
|
||||||
state.taskStatusState.list, state.taskStatusState.map))
|
state.taskStatusState.list, state.taskStatusState.map))
|
||||||
TaskStatusEntity().rebuild((b) => b
|
TaskStatusEntity().rebuild((b) => b
|
||||||
|
|
@ -99,8 +102,57 @@ class TaskScreen extends StatelessWidget {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
body:
|
body: Column(children: [
|
||||||
state.prefState.showKanban ? KanbanViewBuilder() : TaskListBuilder(),
|
// TODO once Firefox is supported
|
||||||
|
if (!state.prefState.hideTaskExtensionBanner &&
|
||||||
|
isDesktop(context) &&
|
||||||
|
(!kIsWeb || isChrome()))
|
||||||
|
ColoredBox(
|
||||||
|
color: Colors.orange,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: IconText(
|
||||||
|
text: localization.taskExtensionBanner,
|
||||||
|
icon: Icons.info_outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
launchUrl(Uri.parse(kTaskExtensionYouTubeUrl));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
localization.watchVideo,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
launchUrl(Uri.parse(kTaskExtensionUrl));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
localization.viewExtension,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: localization.dismiss,
|
||||||
|
onPressed: () {
|
||||||
|
store.dispatch(DismissTaskExtensionBanner());
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.clear),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: state.prefState.showKanban
|
||||||
|
? KanbanViewBuilder()
|
||||||
|
: TaskListBuilder(),
|
||||||
|
),
|
||||||
|
]),
|
||||||
bottomNavigationBar: AppBottomBar(
|
bottomNavigationBar: AppBottomBar(
|
||||||
entityType: EntityType.task,
|
entityType: EntityType.task,
|
||||||
iconButtons: [
|
iconButtons: [
|
||||||
|
|
@ -166,7 +218,7 @@ class TaskScreen extends StatelessWidget {
|
||||||
Icons.add,
|
Icons.add,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
tooltip: localization!.newTask,
|
tooltip: localization.newTask,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ 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
|
||||||
|
'task_extension_banner': 'Add the Chrome extension to manage your tasks',
|
||||||
|
'watch_video': 'Watch Video',
|
||||||
|
'view_extension': 'View Extension',
|
||||||
'reactivate_email': 'Reactivate Email',
|
'reactivate_email': 'Reactivate Email',
|
||||||
'email_reactivated': 'Successfully reactivated email',
|
'email_reactivated': 'Successfully reactivated email',
|
||||||
'template_help': 'Enable using the design as a template',
|
'template_help': 'Enable using the design as a template',
|
||||||
|
|
@ -109980,6 +109983,18 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
_localizedValues[localeCode]!['email_reactivated'] ??
|
_localizedValues[localeCode]!['email_reactivated'] ??
|
||||||
_localizedValues['en']!['email_reactivated']!;
|
_localizedValues['en']!['email_reactivated']!;
|
||||||
|
|
||||||
|
String get taskExtensionBanner =>
|
||||||
|
_localizedValues[localeCode]!['task_extension_banner'] ??
|
||||||
|
_localizedValues['en']!['task_extension_banner']!;
|
||||||
|
|
||||||
|
String get watchVideo =>
|
||||||
|
_localizedValues[localeCode]!['watch_video'] ??
|
||||||
|
_localizedValues['en']!['watch_video']!;
|
||||||
|
|
||||||
|
String get viewExtension =>
|
||||||
|
_localizedValues[localeCode]!['view_extension'] ??
|
||||||
|
_localizedValues['en']!['view_extension']!;
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
|
||||||
String lookup(String? key) {
|
String lookup(String? key) {
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,13 @@ String getPlatformName() {
|
||||||
return 'Unknown';
|
return 'Unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isChrome() {
|
||||||
|
String userAgent = WebUtils.getHtmlValue('user-agent') ?? '';
|
||||||
|
userAgent = userAgent.toLowerCase();
|
||||||
|
|
||||||
|
return userAgent.contains('chrome');
|
||||||
|
}
|
||||||
|
|
||||||
String getNativePlatform() {
|
String getNativePlatform() {
|
||||||
String userAgent = WebUtils.getHtmlValue('user-agent') ?? '';
|
String userAgent = WebUtils.getHtmlValue('user-agent') ?? '';
|
||||||
userAgent = userAgent.toLowerCase();
|
userAgent = userAgent.toLowerCase();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue