Mainly layouts and refacts
This commit is contained in:
parent
59daaaef53
commit
7b3340cbc3
23 changed files with 629 additions and 417 deletions
|
|
@ -317,13 +317,15 @@
|
|||
<Compile Include="Helpers\YavscHelpers.cs" />
|
||||
<Compile Include="Html.cs" />
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="MarkdownEditor.cs">
|
||||
<Compile Include="Markdown\JsBridgeMarkdown.cs" />
|
||||
<Compile Include="Markdown\MarkdownEditor.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>MarkdownEditor.cshtml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MarkdownViewRenderer.cs" />
|
||||
<Compile Include="MarkdownWebViewClient.cs" />
|
||||
<Compile Include="Markdown\MarkdownViewModel.cs" />
|
||||
<Compile Include="Markdown\MarkdownViewRenderer.cs" />
|
||||
<Compile Include="Markdown\MarkdownWebChromeClient.cs" />
|
||||
<Compile Include="OAuth2\YaOAuth2Authenticator.cs" />
|
||||
<Compile Include="Resources\Resource.Designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
@ -338,7 +340,7 @@
|
|||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="google-services.json" />
|
||||
<None Include="MarkdownEditor.cshtml">
|
||||
<None Include="Markdown\MarkdownEditor.cshtml">
|
||||
<Generator>RazorTemplatePreprocessor</Generator>
|
||||
<LastGenOutput>MarkdownEditor.cs</LastGenOutput>
|
||||
<SubType>None</SubType>
|
||||
|
|
|
|||
45
BookAStar/BookAStar.Droid/Markdown/JsBridgeMarkdown.cs
Normal file
45
BookAStar/BookAStar.Droid/Markdown/JsBridgeMarkdown.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Webkit;
|
||||
using Java.Interop;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
public class JsBridgeMarkdown : Java.Lang.Object
|
||||
{
|
||||
readonly WeakReference<MarkdownViewRenderer> hybridWebViewRenderer;
|
||||
|
||||
public JsBridgeMarkdown(MarkdownViewRenderer hybridRenderer)
|
||||
{
|
||||
hybridWebViewRenderer = new WeakReference<MarkdownViewRenderer>(hybridRenderer);
|
||||
}
|
||||
|
||||
[JavascriptInterface]
|
||||
[Export("contentEdited")]
|
||||
public void ContentEdited(string data)
|
||||
{
|
||||
MarkdownViewRenderer hybridRenderer;
|
||||
|
||||
if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
|
||||
{
|
||||
hybridRenderer.Element.Markdown = data;
|
||||
}
|
||||
}
|
||||
|
||||
[JavascriptInterface]
|
||||
[Export("jsLoaded")]
|
||||
public void JSLoaded()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BookAStar.Droid
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -24,7 +24,7 @@ public partial class MarkdownEditor : MarkdownEditorBase
|
|||
#line hidden
|
||||
|
||||
#line 1 "MarkdownEditor.cshtml"
|
||||
public string Model { get; set; }
|
||||
public MarkdownViewModel Model { get; set; }
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
|
@ -36,34 +36,55 @@ WriteLiteral("<!DOCTYPE html>\r\n<html>\r\n<head>\r\n <meta");
|
|||
|
||||
WriteLiteral(" charset=\"utf-8\"");
|
||||
|
||||
WriteLiteral(">\r\n <link");
|
||||
WriteLiteral(">\r\n <style>\r\n .standalone-container {\r\n margin: 0;\r\n " +
|
||||
" width: 100%;\r\n height: 100%;\r\n }\r\n </style>\r\n");
|
||||
|
||||
|
||||
#line 13 "MarkdownEditor.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 13 "MarkdownEditor.cshtml"
|
||||
if (Model.Editable)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <link");
|
||||
|
||||
WriteLiteral(" rel=\"stylesheet\"");
|
||||
|
||||
WriteLiteral(" href=\"quill.snow.css\"");
|
||||
|
||||
WriteLiteral(@" />
|
||||
<style>
|
||||
.standalone-container {
|
||||
margin: 0;
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(@" <style>
|
||||
#bubble-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#bubble-container {
|
||||
width:100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#bubble-container div.ql-editor {
|
||||
margin-top:3em;
|
||||
padding-top:3em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
");
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div");
|
||||
|
||||
#line 30 "MarkdownEditor.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</head>\r\n<body>\r\n <div");
|
||||
|
||||
WriteLiteral(" class=\"standalone-container\"");
|
||||
|
||||
|
|
@ -74,84 +95,124 @@ WriteLiteral(" id=\"bubble-container\"");
|
|||
WriteLiteral(">");
|
||||
|
||||
|
||||
#line 28 "MarkdownEditor.cshtml"
|
||||
Write(Html.Write(Model));
|
||||
#line 34 "MarkdownEditor.cshtml"
|
||||
Write(Html.Write(Model.GetHtml()));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</div>\r\n </div>\r\n \r\n <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"quill.min.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n <script");
|
||||
WriteLiteral("</div>\r\n </div>\r\n <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"jquery.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n <script");
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
|
||||
#line 37 "MarkdownEditor.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 37 "MarkdownEditor.cshtml"
|
||||
if (Model.Editable)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"quill.min.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"showdown.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n <script");
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"to-markdown.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n <script");
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(" src=\"md-helpers.js\"");
|
||||
|
||||
WriteLiteral("></script>\r\n\r\n <script");
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
|
||||
#line 43 "MarkdownEditor.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(@">
|
||||
var toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
WriteLiteral(">\r\n var toolbarOptions = [\r\n [\'bold\', \'italic\', \'underline\', \'str" +
|
||||
"ike\'], // toggled buttons\r\n [\'blockquote\', \'code-block\'],\r\n [{ " +
|
||||
"\'header\': 1 }, { \'header\': 2 }, { \'header\': 3 }], // custom button" +
|
||||
" values\r\n [{ \'list\': \'ordered\' }, { \'list\': \'bullet\' }],\r\n [{ \'indent\'" +
|
||||
": \'-1\' }, { \'indent\': \'+1\' }], // outdent/indent\r\n [\'link\', \'image" +
|
||||
"\', \'video\'],\r\n [\'clean\'] // remove " +
|
||||
"formatting button\r\n ];\r\n\r\n var showImageUI = function (val" +
|
||||
"ue) {\r\n if (value) {\r\n var href = prompt(\'Ente" +
|
||||
"r the URL\');\r\n this.quill.format(\'image\', href);\r\n " +
|
||||
" } else {\r\n this.quill.format(\'image\', false);\r\n " +
|
||||
" }\r\n };\r\n\r\n $(document).ready(function () {\r\n " +
|
||||
" var quill = new Quill(\'#bubble-container\', {\r\n modul" +
|
||||
"es: {\r\n toolbar: toolbarOptions\r\n },\r\n" +
|
||||
" placeholder: \'Composez votre texte ...\',\r\n " +
|
||||
" theme: \'snow\'\r\n });\r\n\r\n function getMD() {\r\n " +
|
||||
" return markdownize($(\'#bubble-container div.ql-editor\').html())\r" +
|
||||
"\n }\r\n quill.on(\'text-change\', function (delta, old" +
|
||||
"Delta, source) {\r\n if (source === \"user\") {\r\n " +
|
||||
" contentEdited(getMD());\r\n }\r\n });\r\n " +
|
||||
" var toolbar = quill.getModule(\'toolbar\');\r\n toolbar." +
|
||||
"addHandler(\'image\', showImageUI);\r\n jsLoaded();\r\n });\r" +
|
||||
"\n </script>\r\n");
|
||||
|
||||
[{ 'header': 1 }, { 'header': 2 }], // custom button values
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
|
||||
['link', 'image', 'video'],
|
||||
['clean'] // remove formatting button
|
||||
];
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
var quill = new Quill('#bubble-container', {
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
placeholder: 'Composez votre texte ...',
|
||||
theme: 'snow'
|
||||
});
|
||||
#line 86 "MarkdownEditor.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
function getMD() {
|
||||
return markdownize($('#bubble-container div.ql-editor').html())
|
||||
}
|
||||
quill.on('text-change', function (delta, oldDelta, source) {
|
||||
if (source === ""user"") {
|
||||
invokeCSharpAction(getMD());
|
||||
}
|
||||
});
|
||||
// TODO implement a dedicated injection
|
||||
invokeCSharpAction(getMD());
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
");
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(">\r\n $(document).ready(function() {\r\n jsLoaded();\r\n });\r\n" +
|
||||
" </script>\r\n");
|
||||
|
||||
|
||||
#line 94 "MarkdownEditor.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</body>\r\n</html>\r\n");
|
||||
|
||||
}
|
||||
}
|
||||
96
BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cshtml
Normal file
96
BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cshtml
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
@model MarkdownViewModel
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.standalone-container {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@if (Model.Editable)
|
||||
{
|
||||
<link rel="stylesheet" href="quill.snow.css" />
|
||||
<style>
|
||||
#bubble-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#bubble-container div.ql-editor {
|
||||
padding-top:3em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</head>
|
||||
<body>
|
||||
<div class="standalone-container">
|
||||
<div id="bubble-container">@Html.Write(Model.GetHtml())</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
@if (Model.Editable)
|
||||
{
|
||||
<script type="text/javascript" src="quill.min.js"></script>
|
||||
<script type="text/javascript" src="showdown.js"></script>
|
||||
<script type="text/javascript" src="to-markdown.js"></script>
|
||||
<script type="text/javascript" src="md-helpers.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
[{ 'header': 1 }, { 'header': 2 }, { 'header': 3 }], // custom button values
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
|
||||
['link', 'image', 'video'],
|
||||
['clean'] // remove formatting button
|
||||
];
|
||||
|
||||
var showImageUI = function (value) {
|
||||
if (value) {
|
||||
var href = prompt('Enter the URL');
|
||||
this.quill.format('image', href);
|
||||
} else {
|
||||
this.quill.format('image', false);
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
var quill = new Quill('#bubble-container', {
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
placeholder: 'Composez votre texte ...',
|
||||
theme: 'snow'
|
||||
});
|
||||
|
||||
function getMD() {
|
||||
return markdownize($('#bubble-container div.ql-editor').html())
|
||||
}
|
||||
quill.on('text-change', function (delta, oldDelta, source) {
|
||||
if (source === "user") {
|
||||
contentEdited(getMD());
|
||||
}
|
||||
});
|
||||
var toolbar = quill.getModule('toolbar');
|
||||
toolbar.addHandler('image', showImageUI);
|
||||
jsLoaded();
|
||||
});
|
||||
</script>
|
||||
}
|
||||
else
|
||||
{
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
jsLoaded();
|
||||
});
|
||||
</script>
|
||||
}
|
||||
</body>
|
||||
</html>
|
||||
29
BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs
Normal file
29
BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
public class MarkdownViewModel
|
||||
{
|
||||
protected static MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown();
|
||||
public string Content { get; set; }
|
||||
public bool Editable { get; set; }
|
||||
public string GetHtml()
|
||||
{
|
||||
return markdown.Transform(Content);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return Content;
|
||||
}
|
||||
}
|
||||
}
|
||||
100
BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs
Normal file
100
BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
using BookAStar.Views;
|
||||
using Android.Webkit;
|
||||
using Xamarin.Forms.Platform.Android;
|
||||
using BookAStar.Droid;
|
||||
using System;
|
||||
using Java.Interop;
|
||||
using System.ComponentModel;
|
||||
using Android.Views;
|
||||
|
||||
[assembly: Xamarin.Forms.ExportRenderer(typeof(MarkdownView), typeof(MarkdownViewRenderer))]
|
||||
namespace BookAStar.Droid
|
||||
{
|
||||
using Markdown;
|
||||
public class MarkdownViewRenderer : ViewRenderer<MarkdownView, WebView>
|
||||
{
|
||||
private WebView editorView;
|
||||
private MarkdownEditor editorTemplate = new MarkdownEditor();
|
||||
const string jsLoadedJavaScriptFunction = "function jsLoaded(){jsBridge.jsLoaded()}";
|
||||
const string contentEditedJavaScriptFunction = "function contentEdited(data){jsBridge.contentEdited(data)}";
|
||||
public WebView EditorView
|
||||
{
|
||||
get
|
||||
{
|
||||
return editorView;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To be called once document finished loading
|
||||
/// </summary>
|
||||
/// <param name="xview"></param>
|
||||
/// <param name="view"></param>
|
||||
public static async void AdjustHeightRequest(MarkdownView xview, WebView view)
|
||||
{
|
||||
if (view == null || xview == null) return;
|
||||
var vch = view.ContentHeight;
|
||||
xview.HeightRequest = vch > xview.MinimumHeightRequest ? vch : xview.MinimumHeightRequest;
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<MarkdownView> e)
|
||||
{
|
||||
base.OnElementChanged(e);
|
||||
if (Control == null)
|
||||
{
|
||||
SetNativeControl(CreateNativeControl());
|
||||
InjectJS(jsLoadedJavaScriptFunction);
|
||||
InjectJS(contentEditedJavaScriptFunction);
|
||||
}
|
||||
if (e.OldElement != null)
|
||||
{
|
||||
// Unsubscribe
|
||||
}
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
// Subscribe
|
||||
editorTemplate.Model = new Markdown.MarkdownViewModel
|
||||
{ Content = e.NewElement.Markdown, Editable = e.NewElement.Editable };
|
||||
var html = editorTemplate.GenerateString();
|
||||
EditorView.LoadDataWithBaseURL("file:///android_asset/",
|
||||
html, "text/html", "utf-8", null);
|
||||
}
|
||||
}
|
||||
|
||||
void InjectJS(string script)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.LoadUrl(string.Format("javascript: {0}", script));
|
||||
}
|
||||
}
|
||||
|
||||
private WebView CreateNativeControl()
|
||||
{
|
||||
editorView = new WebView(Context);
|
||||
EditorView.SetWebChromeClient(
|
||||
new MarkdownWebChromeClient()
|
||||
);
|
||||
EditorView.Settings.BuiltInZoomControls = false;
|
||||
EditorView.Settings.JavaScriptEnabled = true;
|
||||
EditorView.Settings.LoadsImagesAutomatically = true;
|
||||
EditorView.Settings.SetAppCacheEnabled(true);
|
||||
EditorView.Settings.AllowContentAccess = true;
|
||||
EditorView.Settings.AllowFileAccess = true;
|
||||
EditorView.Settings.AllowFileAccessFromFileURLs = true;
|
||||
EditorView.Settings.AllowUniversalAccessFromFileURLs = true;
|
||||
EditorView.Settings.BlockNetworkImage = false;
|
||||
EditorView.Settings.BlockNetworkLoads = false;
|
||||
EditorView.Settings.DomStorageEnabled = true;
|
||||
EditorView.AddJavascriptInterface(new JsBridgeMarkdown(this), "jsBridge");
|
||||
EditorView.ViewTreeObserver.PreDraw += ViewTreeObserver_PreDraw;
|
||||
return EditorView;
|
||||
}
|
||||
|
||||
private void ViewTreeObserver_PreDraw(object sender, ViewTreeObserver.PreDrawEventArgs e)
|
||||
{
|
||||
AdjustHeightRequest(Element, Control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Webkit;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
class MarkdownWebChromeClient : WebChromeClient
|
||||
{
|
||||
/*public override void OnConsoleMessage(string message, int lineNumber, string sourceID)
|
||||
{
|
||||
base.OnConsoleMessage(message, lineNumber, sourceID);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
|
||||
using BookAStar.Views;
|
||||
using Android.Webkit;
|
||||
using Xamarin.Forms.Platform.Android;
|
||||
using BookAStar.Droid;
|
||||
using System;
|
||||
using Java.Interop;
|
||||
using System.ComponentModel;
|
||||
using Android.Views;
|
||||
|
||||
[assembly: Xamarin.Forms.ExportRenderer(typeof(MarkdownView), typeof(MarkdownViewRenderer))]
|
||||
namespace BookAStar.Droid
|
||||
{
|
||||
public class JsBridgeMarkdown : Java.Lang.Object
|
||||
{
|
||||
readonly WeakReference<MarkdownViewRenderer> hybridWebViewRenderer;
|
||||
|
||||
public JsBridgeMarkdown(MarkdownViewRenderer hybridRenderer)
|
||||
{
|
||||
hybridWebViewRenderer = new WeakReference<MarkdownViewRenderer>(hybridRenderer);
|
||||
}
|
||||
|
||||
[JavascriptInterface]
|
||||
[Export("invokeAction")]
|
||||
public void InvokeAction(string data)
|
||||
{
|
||||
MarkdownViewRenderer hybridRenderer;
|
||||
|
||||
if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
|
||||
{
|
||||
hybridRenderer.Element.Markdown = data;
|
||||
MarkdownViewRenderer.AdjustHeightRequest(hybridRenderer.Element,
|
||||
hybridRenderer.EditorView);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MarkdownViewRenderer : ViewRenderer<MarkdownView, WebView>
|
||||
{
|
||||
private WebView editorView;
|
||||
private MarkdownEditor editorTemplate = new MarkdownEditor();
|
||||
private MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown();
|
||||
const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
|
||||
|
||||
public WebView EditorView
|
||||
{
|
||||
get
|
||||
{
|
||||
return editorView;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// To be called once document finished loading
|
||||
/// </summary>
|
||||
/// <param name="xview"></param>
|
||||
/// <param name="view"></param>
|
||||
public static async void AdjustHeightRequest(MarkdownView xview, WebView view)
|
||||
{
|
||||
|
||||
xview.BatchBegin();
|
||||
var vch = view.ContentHeight; // FIXME why not 3?
|
||||
xview.HeightRequest = vch > xview.MinimumHeightRequest ? vch : xview.MinimumHeightRequest;
|
||||
xview.BatchCommit();
|
||||
}
|
||||
|
||||
private void SetMDEditorText(string text)
|
||||
{
|
||||
editorTemplate.Model = (text == null) ? null : markdown.Transform(text);
|
||||
var html = editorTemplate.GenerateString();
|
||||
EditorView.LoadDataWithBaseURL("file:///android_asset/",
|
||||
html, "text/html", "utf-8", null);
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<MarkdownView> e)
|
||||
{
|
||||
base.OnElementChanged(e);
|
||||
if (Control == null)
|
||||
{
|
||||
SetNativeControl(CreateNativeControl());
|
||||
InjectJS(JavaScriptFunction);
|
||||
}
|
||||
if (e.OldElement != null)
|
||||
{
|
||||
// Unsubscribe
|
||||
}
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
// Subscribe
|
||||
var viewclient = new MarkdownWebViewClient(
|
||||
md => { e.NewElement.Markdown = md; });
|
||||
EditorView.SetWebViewClient(viewclient);
|
||||
Control.AddJavascriptInterface(new JsBridgeMarkdown(this), "jsBridge");
|
||||
SetMDEditorText(e.NewElement.Markdown);
|
||||
}
|
||||
}
|
||||
|
||||
void InjectJS(string script)
|
||||
{
|
||||
if (Control != null)
|
||||
{
|
||||
Control.LoadUrl(string.Format("javascript: {0}", script));
|
||||
}
|
||||
}
|
||||
|
||||
private WebView CreateNativeControl()
|
||||
{
|
||||
editorView = new WebView(Context);
|
||||
EditorView.Settings.BuiltInZoomControls = false;
|
||||
EditorView.Settings.JavaScriptEnabled = true;
|
||||
EditorView.Settings.LoadsImagesAutomatically = true;
|
||||
EditorView.Settings.SetAppCacheEnabled(true);
|
||||
EditorView.Settings.AllowContentAccess = true;
|
||||
EditorView.Settings.AllowFileAccess = true;
|
||||
EditorView.Settings.AllowFileAccessFromFileURLs = true;
|
||||
EditorView.Settings.AllowUniversalAccessFromFileURLs = true;
|
||||
EditorView.Settings.BlockNetworkImage = false;
|
||||
EditorView.Settings.BlockNetworkLoads = false;
|
||||
EditorView.Settings.DomStorageEnabled = true;
|
||||
|
||||
// editorView.SetMinimumHeight(300);
|
||||
return EditorView;
|
||||
}
|
||||
// FIXME no impact...
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
MeasureSpecMode widthMode = MeasureSpec.GetMode(widthMeasureSpec);
|
||||
MeasureSpecMode heightMode = MeasureSpec.GetMode(heightMeasureSpec);
|
||||
int widthSize = MeasureSpec.GetSize(widthMeasureSpec);
|
||||
int heightSize = MeasureSpec.GetSize(heightMeasureSpec);
|
||||
int pxHeight = (int)ContextExtensions.ToPixels(Context, Element.HeightRequest);
|
||||
int pxWidth = (int)ContextExtensions.ToPixels(Context, Element.WidthRequest);
|
||||
var measuredWidth = widthMode != MeasureSpecMode.Exactly ? (widthMode != MeasureSpecMode.AtMost ? pxHeight : Math.Min(pxHeight, widthSize)) : widthSize;
|
||||
var measuredHeight = heightMode != MeasureSpecMode.Exactly ? (heightMode != MeasureSpecMode.AtMost ? pxWidth : Math.Min(pxWidth, heightSize)) : heightSize;
|
||||
SetMeasuredDimension(measuredWidth, measuredHeight< Element.HeightRequest ? (int) Element.HeightRequest : measuredHeight);
|
||||
}
|
||||
/*
|
||||
protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
|
||||
{
|
||||
Element.Layout(new Xamarin.Forms.Rectangle(0, 0, ContextExtensions.FromPixels(Context, right - left), ContextExtensions.FromPixels(Context, bottom - top)));
|
||||
base.OnLayout(changed, left, top, right, bottom);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
using System;
|
||||
using Android.App;
|
||||
using Android.Webkit;
|
||||
|
||||
namespace BookAStar.Droid
|
||||
{
|
||||
|
||||
class MarkdownWebViewClient : WebViewClient
|
||||
{
|
||||
Action<string> update;
|
||||
public MarkdownWebViewClient(Action<string> update) : base()
|
||||
{
|
||||
this.update = update;
|
||||
}
|
||||
private static Activity getActivity ()
|
||||
{
|
||||
return (Activity)App.PlatformSpecificInstance;
|
||||
}
|
||||
public string Markdown { get; private set; }
|
||||
public override WebResourceResponse ShouldInterceptRequest(WebView view, IWebResourceRequest request)
|
||||
{
|
||||
if (request.Url.Scheme=="file")
|
||||
{
|
||||
if (request.Url.Path=="/android_asset/validate")
|
||||
{
|
||||
// TODO Better,
|
||||
// by inspecting the form entries from the view
|
||||
Markdown = request.Url.GetQueryParameter("md");
|
||||
update(Markdown);
|
||||
return new WebResourceResponse("application/json", "utf-8" ,200, "Ok", null, null);
|
||||
}
|
||||
}
|
||||
return base.ShouldInterceptRequest(view, request);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
using BookAStar.Interfaces;
|
||||
using BookAStar.Model;
|
||||
using BookAStar.Pages;
|
||||
using BookAStar.ViewModels;
|
||||
using System;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Forms.Mvvm;
|
||||
using XLabs.Forms.Pages;
|
||||
|
|
@ -16,17 +12,20 @@ using XLabs.Enums;
|
|||
|
||||
namespace BookAStar
|
||||
{
|
||||
using Interfaces;
|
||||
using Model;
|
||||
using Pages;
|
||||
using ViewModels;
|
||||
public partial class App : Application // superclass new in 1.3
|
||||
{
|
||||
public static IPlatform PlatformSpecificInstance { get; set; }
|
||||
public static string AppName { get; set; }
|
||||
|
||||
|
||||
// Exists in order to dispose of a static instance strongly typed
|
||||
// TODO : replace all references to this field
|
||||
// by Views resolution, and then, drop it
|
||||
// Exists in order to dispose of a static instance strongly typed,
|
||||
// It Makes smaller code.
|
||||
public static App CurrentApp { get { return Current as App; } }
|
||||
|
||||
|
||||
public static bool MasterPresented
|
||||
{
|
||||
get
|
||||
|
|
@ -65,7 +64,7 @@ namespace BookAStar
|
|||
|
||||
}
|
||||
|
||||
// FIXME Not called
|
||||
// Called Once, at app init
|
||||
private void OnInitialize(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
|
|
@ -81,21 +80,20 @@ namespace BookAStar
|
|||
// Called on rotation
|
||||
private void OnSuspended(object sender, EventArgs e)
|
||||
{
|
||||
// TODO the navigation stack persistence (save)
|
||||
|
||||
// TODO save the navigation stack
|
||||
}
|
||||
|
||||
// called on app startup, after OnStartup, not on rotation
|
||||
private void OnAppResumed(object sender, EventArgs e)
|
||||
{
|
||||
// TODO the navigation stack persistence (restore)
|
||||
// TODO restore the navigation stack
|
||||
base.OnResume();
|
||||
}
|
||||
|
||||
// FIXME Not called ... see OnSuspended
|
||||
// FIXME Not called?
|
||||
private void OnRotation(object sender, EventArgs<Orientation> e)
|
||||
{
|
||||
// TODO the navigation stack persistence (restore?)
|
||||
|
||||
}
|
||||
|
||||
public static GenericConfigSettingsMgr ConfigManager { protected set; get; }
|
||||
|
|
@ -215,9 +213,6 @@ namespace BookAStar
|
|||
, BookQueryPage>((b, p) => p.BindingContext = new BookQueryViewModel(query));
|
||||
App.Current.MainPage.Navigation.PushAsync(page as Page);
|
||||
}
|
||||
|
||||
// TODO système de persistance de l'état de l'appli
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,14 +56,14 @@
|
|||
<Compile Include="Extensions\EnumExtensions.cs" />
|
||||
<Compile Include="Extensions\ImageResourceExtension.cs" />
|
||||
<Compile Include="Factories\ViewFactory.cs" />
|
||||
<Compile Include="Helpers\DataManager.cs" />
|
||||
<Compile Include="Data\DataManager.cs" />
|
||||
<Compile Include="Helpers\ObservableString.cs" />
|
||||
<Compile Include="Interfaces\ILocalEntity.cs" />
|
||||
<Compile Include="Helpers\LocaLEntity.cs" />
|
||||
<Compile Include="Data\LocaLEntity.cs" />
|
||||
<Compile Include="Helpers\NotIdentifiedException.cs" />
|
||||
<Compile Include="Helpers\PageHelpers.cs" />
|
||||
<Compile Include="Helpers\PropertySupport.cs" />
|
||||
<Compile Include="Helpers\RemoteEntityRO.cs" />
|
||||
<Compile Include="Data\RemoteEntityRO.cs" />
|
||||
<Compile Include="Helpers\ServiceNotAvailable.cs" />
|
||||
<Compile Include="Helpers\Settings.cs" />
|
||||
<Compile Include="Helpers\UserHelpers.cs" />
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
<DependentUpon>EventDetail.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Helpers\MainSettings.cs" />
|
||||
<Compile Include="Helpers\RemoteEntity.cs" />
|
||||
<Compile Include="Data\RemoteEntity.cs" />
|
||||
<Compile Include="Interfaces\IPlatform.cs" />
|
||||
<Compile Include="Model\Blog\Blog.cs" />
|
||||
<Compile Include="Model\Blog\BlogTag.cs" />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BookAStar.Helpers
|
||||
namespace BookAStar.Data
|
||||
{
|
||||
using Model;
|
||||
using Model.Blog;
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
using BookAStar.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace BookAStar
|
||||
namespace BookAStar.Data
|
||||
{
|
||||
public class LocalEntity<V, K> : ObservableCollection<V>, ILocalEntity<V, K> where K : IEquatable<K>
|
||||
{
|
||||
|
|
@ -6,7 +6,7 @@ using Newtonsoft.Json;
|
|||
using System.Threading.Tasks;
|
||||
using System.Net;
|
||||
|
||||
namespace BookAStar.Helpers
|
||||
namespace BookAStar.Data
|
||||
{
|
||||
|
||||
public class RemoteEntity<V,K> : LocalEntity<V, K>, ICommand where K : IEquatable<K>
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
using BookAStar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BookAStar.Helpers
|
||||
namespace BookAStar.Data
|
||||
{
|
||||
public class RemoteEntityRO<V,K>: RemoteEntity<V,K> where K: IEquatable<K>
|
||||
{
|
||||
|
|
@ -26,8 +26,8 @@
|
|||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<StackLayout Padding="10,10,10,10">
|
||||
|
||||
<ScrollView>
|
||||
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||
<ListView RefreshCommand="{Binding RefreshQueries}" IsPullToRefreshEnabled="True"
|
||||
ItemsSource="{Binding Queries}" x:Name="list" ItemTapped="OnViewDetail" HasUnevenRows="true" RowHeight="80">
|
||||
<ListView.ItemTemplate HeightRequest="80" VerticalOptions="StartAndExpand">
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontSize="12" FontFamily="Italic"/>
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Vertical" VerticalOptions="StartAndExpand">
|
||||
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
|
||||
<Label Text="{Binding Previsionnal}"/>
|
||||
<Label Text="{Binding Id}" HorizontalTextAlignment="End"/>
|
||||
|
|
@ -58,5 +58,6 @@
|
|||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
||||
</ContentPage>
|
||||
|
|
@ -20,5 +20,18 @@ namespace BookAStar.Pages
|
|||
BookQueryData data = e.Item as BookQueryData;
|
||||
App.NavigationService.NavigateTo<BookQueryPage>(true,data);
|
||||
}
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
{
|
||||
/* TODO find a responsive layout
|
||||
if (width > height)
|
||||
{
|
||||
mainLayout.Orientation = StackOrientation.Horizontal;
|
||||
}
|
||||
else
|
||||
{
|
||||
mainLayout.Orientation = StackOrientation.Vertical;
|
||||
} */
|
||||
base.OnSizeAllocated(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,16 @@
|
|||
</ContentPage.Resources>
|
||||
|
||||
<StackLayout x:Name="bookQueryLayout">
|
||||
|
||||
<StackLayout Orientation="Vertical">
|
||||
<Image Source="{Binding Client.AvatarOrNot}" Aspect="AspectFit" VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}"/>
|
||||
<Label Text="{Binding Client.UserName}"/>
|
||||
<Label Text="{Binding EventDate, StringFormat='le {0:dddd d MMMM yyyy à hh:mm}'}" />
|
||||
<Label Text="{Binding Location.Address}" />
|
||||
<Label Text="{Binding Previsional}" />
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
|
||||
<maps:Map x:Name="map" VerticalOptions="FillAndExpand"></maps:Map>
|
||||
<Button Text="Faire un devis" Clicked="MakeAnEstimate" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
||||
|
|
@ -80,6 +80,18 @@ namespace BookAStar.Pages
|
|||
App.NavigationService.NavigateTo<EditEstimatePage>(true,
|
||||
new EditEstimateViewModel(e));
|
||||
}
|
||||
|
||||
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
{
|
||||
if (width > height)
|
||||
{
|
||||
bookQueryLayout.Orientation = StackOrientation.Horizontal;
|
||||
}
|
||||
else
|
||||
{
|
||||
bookQueryLayout.Orientation = StackOrientation.Vertical;
|
||||
}
|
||||
base.OnSizeAllocated(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
</Style>
|
||||
<converters:EnumConverter x:Key="enumToInt" />
|
||||
<converters:BooleanToObjectConverter x:Key="boolToStyleImage" x:TypeArguments="Style">
|
||||
|
||||
|
||||
<converters:BooleanToObjectConverter.FalseObject>
|
||||
<Style TargetType="Image">
|
||||
<Setter Property="HeightRequest" Value="20" />
|
||||
<Setter Property="Source"
|
||||
<Setter Property="Source"
|
||||
Value="{extensions:ImageResource BookAStar.Images.Validation.error.png}" />
|
||||
</Style>
|
||||
</converters:BooleanToObjectConverter.FalseObject>
|
||||
|
|
@ -30,58 +30,73 @@
|
|||
<converters:BooleanToObjectConverter.TrueObject>
|
||||
<Style TargetType="Image">
|
||||
<Setter Property="HeightRequest" Value="20" />
|
||||
<Setter Property="Source"
|
||||
<Setter Property="Source"
|
||||
Value="{extensions:ImageResource BookAStar.Images.Validation.success.png}" />
|
||||
</Style>
|
||||
</converters:BooleanToObjectConverter.TrueObject>
|
||||
|
||||
|
||||
</converters:BooleanToObjectConverter>
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<ScrollView>
|
||||
|
||||
<StackLayout x:Name="mainStackLayout">
|
||||
|
||||
<Label Text="Description de la ligne de facture"
|
||||
Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<Editor VerticalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
|
||||
<Editor.Behaviors>
|
||||
<behaviors:EditorMaxLengthValidator x:Name="descriptionValidator" MaxLength="512" />
|
||||
</Editor.Behaviors>
|
||||
</Editor>
|
||||
<Image Style="{Binding Source={x:Reference descriptionValidator},
|
||||
<Label Text="Description de la ligne de facture"
|
||||
Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
|
||||
<Editor HorizontalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
|
||||
<Editor.Behaviors>
|
||||
<behaviors:EditorMaxLengthValidator x:Name="descriptionValidator" MaxLength="512" />
|
||||
</Editor.Behaviors>
|
||||
</Editor>
|
||||
<Image HorizontalOptions="End" Style="{Binding Source={x:Reference descriptionValidator},
|
||||
Path=IsValid,
|
||||
Converter={StaticResource boolToStyleImage}}" />
|
||||
<Label Text="Durée de la prestation"
|
||||
Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Entry Placeholder="Durée" Keyboard="Numeric" Style="{StaticResource BigEntry}"
|
||||
Text="{Binding DurationValue, Mode=TwoWay}" />
|
||||
<views:EnumPicker x:Name="picker" Style="{StaticResource PickerStyle}"
|
||||
EnumSource="{Binding DurationUnit}"
|
||||
Title="Unité de temps"
|
||||
SelectedItem="{Binding DurationUnit, Mode=TwoWay}">
|
||||
</views:EnumPicker>
|
||||
</StackLayout>
|
||||
|
||||
<Label Text="Quantité facturée" Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<Entry Text="{Binding Count, Mode=TwoWay}" Placeholder="Quantité" Keyboard="Numeric"
|
||||
Style="{StaticResource BigEntry}"/>
|
||||
<Label Text="Prix unitaire" Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Entry Text="{Binding UnitaryCostText, Mode=TwoWay}" Placeholder="Prix"
|
||||
Keyboard="Numeric" Style="{StaticResource BigEntry}">
|
||||
<Entry.Behaviors>
|
||||
<behaviors:DecimalValidatorBehavior x:Name="unitCostValidator" />
|
||||
</Entry.Behaviors>
|
||||
</Entry>
|
||||
<Label Text="€" Style="{StaticResource BigLabel}" />
|
||||
<Image x:Name="unitaryCostSuccessErrorImage"
|
||||
Style="{Binding Source={x:Reference unitCostValidator},
|
||||
</StackLayout>
|
||||
|
||||
<Label Text="Durée de la prestation"
|
||||
Style="{StaticResource InputLabelStyle}">
|
||||
</Label>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Entry Placeholder="Durée" Keyboard="Numeric" Style="{StaticResource BigEntry}"
|
||||
Text="{Binding DurationValue, Mode=TwoWay, StringFormat='{0}'}" >
|
||||
<Entry.Behaviors>
|
||||
<behaviors:DecimalValidatorBehavior x:Name="durationValidator" />
|
||||
</Entry.Behaviors>
|
||||
</Entry>
|
||||
<views:EnumPicker x:Name="picker" Style="{StaticResource PickerStyle}"
|
||||
EnumSource="{Binding DurationUnit}"
|
||||
Title="Unité de temps"
|
||||
SelectedItem="{Binding DurationUnit, Mode=TwoWay}">
|
||||
</views:EnumPicker>
|
||||
<Image x:Name="durationSuccessErrorImage"
|
||||
Style="{Binding Source={x:Reference durationValidator},
|
||||
Path=IsValid,
|
||||
Converter={StaticResource boolToStyleImage}}" />
|
||||
</StackLayout>
|
||||
<Button Text="Valider cette ligne de devis"
|
||||
Command="{Binding ValidateCommand}"
|
||||
Clicked="OnValidateClicked"></Button>
|
||||
</StackLayout>
|
||||
|
||||
<Label Text="Quantité facturée" Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<Entry Text="{Binding Count, Mode=TwoWay}" Placeholder="Quantité" Keyboard="Numeric"
|
||||
Style="{StaticResource BigEntry}"/>
|
||||
<Label Text="Prix unitaire" Style="{StaticResource InputLabelStyle}"></Label>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Entry Text="{Binding UnitaryCostText, Mode=TwoWay}" Placeholder="Prix"
|
||||
Keyboard="Numeric" Style="{StaticResource BigEntry}">
|
||||
<Entry.Behaviors>
|
||||
<behaviors:DecimalValidatorBehavior x:Name="unitCostValidator" />
|
||||
</Entry.Behaviors>
|
||||
</Entry>
|
||||
<Label Text="€" Style="{StaticResource BigLabel}" />
|
||||
<Image x:Name="unitaryCostSuccessErrorImage"
|
||||
Style="{Binding Source={x:Reference unitCostValidator},
|
||||
Path=IsValid,
|
||||
Converter={StaticResource boolToStyleImage}}" />
|
||||
</StackLayout>
|
||||
|
||||
<Button Text="Valider cette ligne de devis"
|
||||
Command="{Binding ValidateCommand}"
|
||||
Clicked="OnValidateClicked"></Button>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
|
|
|
|||
|
|
@ -16,62 +16,67 @@
|
|||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<ScrollView>
|
||||
<StackLayout Padding="10,10,10,10">
|
||||
<StackLayout Orientation="Horizontal" Padding="10,10,10,10" View.VerticalOptions="CenterAndExpand">
|
||||
<Label Text="{Binding Client.UserName}" LineBreakMode="WordWrap" View.VerticalOptions="CenterAndExpand"></Label>
|
||||
<Label Text="{Binding Query.Location.Address}" LineBreakMode="WordWrap" View.VerticalOptions="CenterAndExpand"></Label>
|
||||
<Label Text="{Binding Query.EventDate, StringFormat='{0:dddd d MMMM yyyy à hh:mm}'}" LineBreakMode="WordWrap" View.VerticalOptions="CenterAndExpand"></Label>
|
||||
</StackLayout>
|
||||
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||
|
||||
<views:MarkdownView x:Name="mdview"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
View.VerticalOptions="CenterAndExpand"
|
||||
Markdown="{Binding Description, Mode=TwoWay}"
|
||||
MinimumHeightRequest="160"
|
||||
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,
|
||||
Property=Height,
|
||||
Factor=.6}"
|
||||
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,
|
||||
Property=Width,
|
||||
Factor=1}"
|
||||
></views:MarkdownView>
|
||||
|
||||
|
||||
<ListView x:Name="BillListView" ItemsSource="{Binding Bill}"
|
||||
VerticalOptions="End" MinimumHeightRequest="30" >
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate >
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="90" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Text="{Binding Description}"
|
||||
Grid.Row="0" Grid.Column="0" ></Label>
|
||||
<Label Text="{Binding Duration, StringFormat=\{0\}}"
|
||||
Grid.Row="0" Grid.Column="1" ></Label>
|
||||
<Label Text="{Binding Count}"
|
||||
Grid.Row="0" Grid.Column="2" ></Label>
|
||||
<Label Text="{Binding UnitaryCost}"
|
||||
Grid.Row="0" Grid.Column="3"
|
||||
FontFamily="Monospace"></Label>
|
||||
</Grid>
|
||||
<Grid MinimumHeightRequest="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Client.UserName}" ></Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Query.Location.Address}" ></Label>
|
||||
<Label Grid.Row="0" Grid.Column="2" Text="{Binding Query.EventDate, StringFormat='{0:dddd d MMMM yyyy à hh:mm}'}" ></Label>
|
||||
</Grid>
|
||||
|
||||
<views:MarkdownView x:Name="mdview"
|
||||
Editable="True"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
Markdown="{Binding Description, Mode=TwoWay}"
|
||||
VerticalOptions="Start"
|
||||
/>
|
||||
<StackLayout x:Name="biAnVaLayout">
|
||||
<ListView x:Name="BillListView" ItemsSource="{Binding Bill}"
|
||||
MinimumHeightRequest="40" HasUnevenRows="true" VerticalOptions="FillAndExpand"
|
||||
HeightRequest="40">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate >
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<Grid MinimumHeightRequest="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="90" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Text="{Binding Description}"
|
||||
Grid.Row="0" Grid.Column="0" ></Label>
|
||||
<Label Text="{Binding Duration, StringFormat=\{0\}}"
|
||||
Grid.Row="0" Grid.Column="1" ></Label>
|
||||
<Label Text="{Binding Count}"
|
||||
Grid.Row="0" Grid.Column="2" ></Label>
|
||||
<Label Text="{Binding UnitaryCost}"
|
||||
Grid.Row="0" Grid.Column="3"
|
||||
FontFamily="Monospace"></Label>
|
||||
</Grid>
|
||||
</ViewCell.View>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<Button Text="Ajouter une ligne de facture" Clicked="OnNewCommanLine"></Button>
|
||||
<Label FormattedText="{Binding FormattedTotal}"/>
|
||||
<Button Text="Valider ce devis"></Button>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<StackLayout Orientation="Vertical">
|
||||
<Button Text="Ajouter une ligne de facture" Clicked="OnNewCommanLine"></Button>
|
||||
<Label FormattedText="{Binding FormattedTotal}"/>
|
||||
<Button Text="Valider ce devis" Clicked="OnEstimateValidated" ></Button>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
|
|
@ -1,21 +1,10 @@
|
|||
using BookAStar.Model;
|
||||
using BookAStar.Model.Workflow;
|
||||
using BookAStar.ViewModels;
|
||||
using BookAStar.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Internals;
|
||||
using XLabs.Forms.Services;
|
||||
using XLabs.Ioc;
|
||||
using XLabs.Platform.Services;
|
||||
|
||||
namespace BookAStar.Pages
|
||||
{
|
||||
using Model.Workflow;
|
||||
using ViewModels;
|
||||
public partial class EditEstimatePage : ContentPage
|
||||
{
|
||||
|
||||
|
|
@ -25,16 +14,17 @@ namespace BookAStar.Pages
|
|||
BindingContext = model;
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
((EditEstimateViewModel)BindingContext).PropertyChanged += EditEstimatePage_PropertyChanged;
|
||||
|
||||
}
|
||||
|
||||
private void EditEstimatePage_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
|
||||
if (width > height)
|
||||
{
|
||||
biAnVaLayout.Orientation = StackOrientation.Horizontal;
|
||||
}
|
||||
else
|
||||
{
|
||||
biAnVaLayout.Orientation = StackOrientation.Vertical;
|
||||
}
|
||||
base.OnSizeAllocated(width, height);
|
||||
}
|
||||
|
||||
protected void OnNewCommanLine(object sender, EventArgs e)
|
||||
|
|
@ -52,6 +42,10 @@ namespace BookAStar.Pages
|
|||
true,
|
||||
new object[] { lineView } );
|
||||
}
|
||||
|
||||
|
||||
protected void OnEstimateValidated(object sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ namespace BookAStar.Views
|
|||
public static readonly BindableProperty MarkdownProperty = BindableProperty.Create(
|
||||
"Markdown", typeof(string), typeof(MarkdownView), null, BindingMode.TwoWay
|
||||
);
|
||||
|
||||
public static readonly BindableProperty EditableProperty = BindableProperty.Create(
|
||||
"Editable", typeof(bool), typeof(MarkdownView), false, BindingMode.OneWay
|
||||
);
|
||||
public string Markdown
|
||||
{
|
||||
get
|
||||
|
|
@ -36,6 +38,14 @@ namespace BookAStar.Views
|
|||
}
|
||||
}
|
||||
}
|
||||
private bool editable;
|
||||
public bool Editable
|
||||
{
|
||||
get {
|
||||
return (bool) GetValue(EditableProperty);
|
||||
}
|
||||
set { SetValue (EditableProperty, value); }
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> Modified;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue