Settings
This commit is contained in:
parent
dab542e652
commit
a1db40aab1
|
|
@ -156,7 +156,7 @@ class _EmailSettingsState extends State<EmailSettings>
|
||||||
label: localization.enableMarkup,
|
label: localization.enableMarkup,
|
||||||
helpLabel: localization.enableMarkupHelp,
|
helpLabel: localization.enableMarkupHelp,
|
||||||
value: settings.enableEmailMarkup,
|
value: settings.enableEmailMarkup,
|
||||||
iconData: FontAwesomeIcons.envelope,
|
iconData: FontAwesomeIcons.solidEnvelope,
|
||||||
showBlank: state.settingsUIState.isFiltered,
|
showBlank: state.settingsUIState.isFiltered,
|
||||||
onChanged: (value) => viewModel.onSettingsChanged(
|
onChanged: (value) => viewModel.onSettingsChanged(
|
||||||
settings.rebuild((b) => b..enableEmailMarkup = value)),
|
settings.rebuild((b) => b..enableEmailMarkup = value)),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,30 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
|
|
||||||
|
const String kExamplePage = '''
|
||||||
|
<!DOCTYPE html><html>
|
||||||
|
<head><title>Navigation Delegate Example</title></head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
The navigation delegate is set to block navigation to the youtube website.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<ul><a href="https://www.youtube.com/">https://www.youtube.com/</a></ul>
|
||||||
|
<ul><a href="https://www.google.com/">https://www.google.com/</a></ul>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
''';
|
||||||
|
|
||||||
class TemplatesAndReminders extends StatefulWidget {
|
class TemplatesAndReminders extends StatefulWidget {
|
||||||
const TemplatesAndReminders({
|
const TemplatesAndReminders({
|
||||||
|
|
@ -18,12 +38,10 @@ class TemplatesAndReminders extends StatefulWidget {
|
||||||
_TemplatesAndRemindersState createState() => _TemplatesAndRemindersState();
|
_TemplatesAndRemindersState createState() => _TemplatesAndRemindersState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
class _TemplatesAndRemindersState extends State<TemplatesAndReminders> {
|
||||||
with SingleTickerProviderStateMixin {
|
|
||||||
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
FocusScopeNode _focusNode;
|
FocusScopeNode _focusNode;
|
||||||
TabController _controller;
|
|
||||||
|
|
||||||
bool autoValidate = false;
|
bool autoValidate = false;
|
||||||
|
|
||||||
|
|
@ -35,13 +53,11 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_focusNode = FocusScopeNode();
|
_focusNode = FocusScopeNode();
|
||||||
_controller = TabController(vsync: this, length: 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_focusNode.dispose();
|
_focusNode.dispose();
|
||||||
_controller.dispose();
|
|
||||||
_controllers.forEach((dynamic controller) {
|
_controllers.forEach((dynamic controller) {
|
||||||
controller.removeListener(_onChanged);
|
controller.removeListener(_onChanged);
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
|
|
@ -82,62 +98,148 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
final state = viewModel.state;
|
final state = viewModel.state;
|
||||||
|
final settings = viewModel.settings;
|
||||||
|
|
||||||
|
final String contentBase64 =
|
||||||
|
base64Encode(const Utf8Encoder().convert(kExamplePage));
|
||||||
|
final url = 'data:text/html;base64,$contentBase64';
|
||||||
|
print('url: $url');
|
||||||
|
|
||||||
|
|
||||||
return SettingsScaffold(
|
return SettingsScaffold(
|
||||||
title: localization.templatesAndReminders,
|
title: localization.templatesAndReminders,
|
||||||
onSavePressed: viewModel.onSavePressed,
|
onSavePressed: viewModel.onSavePressed,
|
||||||
appBarBottom: TabBar(
|
body: Column(
|
||||||
key: ValueKey(state.settingsUIState.updatedAt),
|
|
||||||
controller: _controller,
|
|
||||||
isScrollable: true,
|
|
||||||
tabs: [
|
|
||||||
Tab(
|
|
||||||
text: localization.invoices,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.quotes,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.payments,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.firstReminder,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.secondReminder,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.thirdReminder,
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: localization.endlessReminder,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: AppTabForm(
|
|
||||||
tabController: _controller,
|
|
||||||
formKey: _formKey,
|
|
||||||
focusNode: _focusNode,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
TemplateEditor(),
|
AppForm(
|
||||||
TemplateEditor(),
|
formKey: _formKey,
|
||||||
TemplateEditor(),
|
children: <Widget>[
|
||||||
TemplateEditor(),
|
FormCard(
|
||||||
TemplateEditor(),
|
children: <Widget>[
|
||||||
TemplateEditor(),
|
DecoratedFormField(
|
||||||
TemplateEditor(),
|
label: localization.subject,
|
||||||
|
//controller: _subjectController,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.body,
|
||||||
|
//controller: _bodyController,
|
||||||
|
maxLines: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: WebView(
|
||||||
|
initialUrl: url,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TemplateEditor extends StatelessWidget {
|
class TemplateEditor extends StatefulWidget {
|
||||||
|
const TemplateEditor({this.subject, this.body});
|
||||||
|
|
||||||
|
final String subject;
|
||||||
|
final String body;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_TemplateEditorState createState() => _TemplateEditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TemplateEditorState extends State<TemplateEditor> {
|
||||||
|
|
||||||
|
final Completer<WebViewController> _controller =
|
||||||
|
Completer<WebViewController>();
|
||||||
|
|
||||||
|
final _subjectController = TextEditingController();
|
||||||
|
final _bodyController = TextEditingController();
|
||||||
|
|
||||||
|
List<TextEditingController> _controllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_controllers = [
|
||||||
|
_subjectController,
|
||||||
|
_bodyController,
|
||||||
|
];
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||||
|
|
||||||
|
_subjectController.text = widget.subject;
|
||||||
|
_bodyController.text = widget.body;
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.addListener(_onChanged));
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controllers.forEach((dynamic controller) {
|
||||||
|
controller.removeListener(_onChanged);
|
||||||
|
controller.dispose();
|
||||||
|
});
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
print('## CHANGED: ${_subjectController.text} - ${_bodyController.text}');
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product.rebuild((b) => b
|
||||||
|
..customValue2 = _custom2Controller.text.trim());
|
||||||
|
if (product != widget.viewModel.product) {
|
||||||
|
widget.viewModel.onChanged(product);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text('test')
|
FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.subject,
|
||||||
|
controller: _subjectController,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.body,
|
||||||
|
controller: _bodyController,
|
||||||
|
maxLines: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
FormCard(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
WebView(
|
||||||
|
//initialUrl: url,
|
||||||
|
initialUrl: 'https://flutter.dev',
|
||||||
|
javascriptMode: JavascriptMode.unrestricted,
|
||||||
|
onWebViewCreated: (WebViewController webViewController) {
|
||||||
|
_controller.complete(webViewController);
|
||||||
|
},
|
||||||
|
onPageFinished: (String url) {
|
||||||
|
print('Page finished loading: $url');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text('subject'),
|
||||||
|
SizedBox(height: 15),
|
||||||
|
Text('body'),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
pubspec.lock
59
pubspec.lock
|
|
@ -14,7 +14,7 @@ packages:
|
||||||
name: analyzer_plugin
|
name: analyzer_plugin
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0"
|
version: "0.2.1"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -42,7 +42,7 @@ packages:
|
||||||
name: build
|
name: build
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
build_config:
|
build_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -63,7 +63,7 @@ packages:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.2.1"
|
||||||
build_runner:
|
build_runner:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
|
@ -91,21 +91,21 @@ packages:
|
||||||
name: built_value
|
name: built_value
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.7.1"
|
version: "6.8.2"
|
||||||
built_value_generator:
|
built_value_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: built_value_generator
|
name: built_value_generator
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.7.1"
|
version: "6.8.2"
|
||||||
cached_network_image:
|
cached_network_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cached_network_image
|
name: cached_network_image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.2+1"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -217,7 +217,7 @@ packages:
|
||||||
name: fixnum
|
name: fixnum
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.9"
|
version: "0.10.11"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -229,7 +229,7 @@ packages:
|
||||||
name: flutter_cache_manager
|
name: flutter_cache_manager
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.3"
|
||||||
flutter_colorpicker:
|
flutter_colorpicker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -267,7 +267,7 @@ packages:
|
||||||
name: flutter_slidable
|
name: flutter_slidable
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.3"
|
version: "0.5.4"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -298,14 +298,14 @@ packages:
|
||||||
name: glob
|
name: glob
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.7"
|
version: "1.2.0"
|
||||||
google_sign_in:
|
google_sign_in:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: google_sign_in
|
name: google_sign_in
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.7"
|
version: "4.0.11"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -347,14 +347,14 @@ packages:
|
||||||
name: image_picker
|
name: image_picker
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.1+4"
|
version: "0.6.1+10"
|
||||||
in_app_purchase:
|
in_app_purchase:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: in_app_purchase
|
name: in_app_purchase
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1+4"
|
version: "0.2.2+2"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -453,6 +453,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.0"
|
version: "1.6.0"
|
||||||
|
node_interop:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_interop
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
node_io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_io
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1+2"
|
||||||
node_preamble:
|
node_preamble:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -494,7 +508,7 @@ packages:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.4.0"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -578,21 +592,21 @@ packages:
|
||||||
name: sentry
|
name: sentry
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.3.1"
|
||||||
share:
|
share:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share
|
name: share
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.2+1"
|
version: "0.6.3+1"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.3+4"
|
version: "0.5.4+3"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -660,7 +674,7 @@ packages:
|
||||||
name: sqflite
|
name: sqflite
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.7"
|
version: "1.1.7+2"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -744,7 +758,7 @@ packages:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.4"
|
version: "5.2.1"
|
||||||
usage:
|
usage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -787,6 +801,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.15"
|
version: "1.0.15"
|
||||||
|
webview_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: webview_flutter
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.15+1"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ dependencies:
|
||||||
native_pdf_renderer: any
|
native_pdf_renderer: any
|
||||||
flutter_colorpicker: any
|
flutter_colorpicker: any
|
||||||
flutter_json_widget: ^1.0.2
|
flutter_json_widget: ^1.0.2
|
||||||
|
webview_flutter: ^0.3.15+1
|
||||||
#quick_actions: ^0.2.1
|
#quick_actions: ^0.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue