Browse Source

fix: iOS Nullable

pull/10190/head
Giuseppe Lippolis 4 years ago
parent
commit
80dc4dd0b7
  1. 5
      src/iOS/Avalonia.iOS/PlatformSettings.cs
  2. 8
      src/iOS/Avalonia.iOS/Storage/IOSStorageItem.cs
  3. 81
      src/iOS/Avalonia.iOS/TextInputResponder.cs

5
src/iOS/Avalonia.iOS/PlatformSettings.cs

@ -1,8 +1,7 @@
#nullable enable
using System; using System;
using System.Linq;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Foundation;
using UIKit; using UIKit;
namespace Avalonia.iOS; namespace Avalonia.iOS;
@ -10,7 +9,7 @@ namespace Avalonia.iOS;
// TODO: ideally should be created per view/activity. // TODO: ideally should be created per view/activity.
internal class PlatformSettings : DefaultPlatformSettings internal class PlatformSettings : DefaultPlatformSettings
{ {
private PlatformColorValues _lastColorValues; private PlatformColorValues? _lastColorValues;
public override PlatformColorValues GetColorValues() public override PlatformColorValues GetColorValues()
{ {

8
src/iOS/Avalonia.iOS/Storage/IOSStorageItem.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -24,8 +23,11 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
using (var doc = new UIDocument(url)) using (var doc = new UIDocument(url))
{ {
_filePath = doc.FileUrl?.Path ?? url.FilePathUrl.Path; _filePath = doc.FileUrl?.Path ?? url.FilePathUrl?.Path ?? string.Empty;
Name = doc.LocalizedName ?? System.IO.Path.GetFileName(_filePath) ?? url.FilePathUrl.LastPathComponent; Name = doc.LocalizedName
?? System.IO.Path.GetFileName(_filePath)
?? url.FilePathUrl?.LastPathComponent
?? string.Empty;
} }
} }

81
src/iOS/Avalonia.iOS/TextInputResponder.cs

@ -1,14 +1,13 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Avalonia.Controls.Presenters; using Avalonia.Controls.Presenters;
using Foundation;
using ObjCRuntime;
using Avalonia.Input.TextInput;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Logging; using Avalonia.Logging;
using CoreGraphics; using CoreGraphics;
using Foundation;
using ObjCRuntime;
using UIKit; using UIKit;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo // ReSharper disable StringLiteralTypo
@ -25,6 +24,9 @@ partial class AvaloniaView
[Adopts("UIKeyInput")] [Adopts("UIKeyInput")]
partial class TextInputResponder : UIResponder, IUITextInput partial class TextInputResponder : UIResponder, IUITextInput
{ {
private static AvaloniaEmptyTextPosition? _emptyPosition;
private static AvaloniaEmptyTextPosition EmptyPosition => _emptyPosition ??= new();
private class AvaloniaTextRange : UITextRange, INSCopying private class AvaloniaTextRange : UITextRange, INSCopying
{ {
private UITextPosition? _start; private UITextPosition? _start;
@ -67,6 +69,15 @@ partial class AvaloniaView
public NSObject Copy(NSZone? zone) => new AvaloniaTextPosition(Index); public NSObject Copy(NSZone? zone) => new AvaloniaTextPosition(Index);
} }
private class AvaloniaEmptyTextPosition : UITextPosition, INSCopying
{
public AvaloniaEmptyTextPosition()
{
}
public NSObject Copy(NSZone? zone) => this;
}
public TextInputResponder(AvaloniaView view, ITextInputMethodClient client) public TextInputResponder(AvaloniaView view, ITextInputMethodClient client)
{ {
_view = view; _view = view;
@ -93,7 +104,25 @@ partial class AvaloniaView
public override NSString TextInputContextIdentifier => new NSString(Guid.NewGuid().ToString()); public override NSString TextInputContextIdentifier => new NSString(Guid.NewGuid().ToString());
public override UITextInputMode TextInputMode => UITextInputMode.CurrentInputMode; public override UITextInputMode TextInputMode
{
get
{
var mode = UITextInputMode.CurrentInputMode;
// Can be empty see https://developer.apple.com/documentation/uikit/uitextinputmode/1614522-activeinputmodes
if (mode is null && UITextInputMode.ActiveInputModes.Length > 0)
{
mode = UITextInputMode.ActiveInputModes[0];
}
// See: https://stackoverflow.com/a/33337483/20894223
if (mode is null)
{
using var tv = new UITextView();
mode = tv.TextInputMode;
}
return mode;
}
}
[DllImport("/usr/lib/libobjc.dylib")] [DllImport("/usr/lib/libobjc.dylib")]
private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg); private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg);
@ -105,8 +134,8 @@ partial class AvaloniaView
private readonly AvaloniaView _view; private readonly AvaloniaView _view;
private string? _markedText; private string? _markedText;
private void SurroundingTextChanged(object? sender, EventArgs e) private void SurroundingTextChanged(object? sender, EventArgs e)
{ {
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "SurroundingTextChanged"); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "SurroundingTextChanged");
@ -153,9 +182,9 @@ partial class AvaloniaView
switch (ReturnKeyType) switch (ReturnKeyType)
{ {
case UIReturnKeyType.Done: case UIReturnKeyType.Done:
case UIReturnKeyType.Go: case UIReturnKeyType.Go:
case UIReturnKeyType.Send: case UIReturnKeyType.Send:
case UIReturnKeyType.Search: case UIReturnKeyType.Search:
ResignFirstResponder(); ResignFirstResponder();
break; break;
} }
@ -164,7 +193,7 @@ partial class AvaloniaView
TextInput(text); TextInput(text);
} }
void IUIKeyInput.DeleteBackward() => KeyPress(Key.Back); void IUIKeyInput.DeleteBackward() => KeyPress(Key.Back);
bool IUIKeyInput.HasText => true; bool IUIKeyInput.HasText => true;
@ -176,8 +205,8 @@ partial class AvaloniaView
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.TextInRange {start} {end}", r.StartIndex, r.EndIndex); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.TextInRange {start} {end}", r.StartIndex, r.EndIndex);
string result = ""; string result = "";
if(string.IsNullOrEmpty(_markedText)) if (string.IsNullOrEmpty(_markedText))
result = s.Text[r.StartIndex .. r.EndIndex]; result = s.Text[r.StartIndex..r.EndIndex];
else else
{ {
var span = new CombinedSpan3<char>(s.Text.AsSpan().Slice(0, s.CursorOffset), var span = new CombinedSpan3<char>(s.Text.AsSpan().Slice(0, s.CursorOffset),
@ -214,7 +243,7 @@ partial class AvaloniaView
void IUITextInput.UnmarkText() void IUITextInput.UnmarkText()
{ {
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.UnmarkText"); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.UnmarkText");
if(_markedText == null) if (_markedText == null)
return; return;
var commitString = _markedText; var commitString = _markedText;
_markedText = null; _markedText = null;
@ -239,15 +268,15 @@ partial class AvaloniaView
Logger.TryGet(LogEventLevel.Debug, ImeLog) Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, "IUIKeyInput.GetPosition {start} {offset}", pos.Index, (int)offset); ?.Log(null, "IUIKeyInput.GetPosition {start} {offset}", pos.Index, (int)offset);
var res = GetPositionCore(pos, offset); var res = GetPositionCore(pos, offset);
Logger.TryGet(LogEventLevel.Debug, ImeLog) Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index)); ?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index));
return res!; return res!;
} }
private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition pos, nint offset) private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition pos, nint offset)
{ {
var end = pos.Index + (int)offset; var end = pos.Index + (int)offset;
if (end < 0) if (end < 0)
return null!; return null!;
@ -261,14 +290,14 @@ partial class AvaloniaView
{ {
var pos = (AvaloniaTextPosition)fromPosition; var pos = (AvaloniaTextPosition)fromPosition;
Logger.TryGet(LogEventLevel.Debug, ImeLog) Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index, inDirection, (int)offset); ?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index, inDirection, (int)offset);
var res = GetPositionCore(pos, inDirection, offset); var res = GetPositionCore(pos, inDirection, offset);
Logger.TryGet(LogEventLevel.Debug, ImeLog) Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index)); ?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index));
return res!; return res!;
} }
private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition fromPosition, UITextLayoutDirection inDirection, private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition fromPosition, UITextLayoutDirection inDirection,
nint offset) nint offset)
{ {
@ -348,7 +377,7 @@ partial class AvaloniaView
CGRect IUITextInput.GetFirstRectForRange(UITextRange range) CGRect IUITextInput.GetFirstRectForRange(UITextRange range)
{ {
Logger.TryGet(LogEventLevel.Debug, ImeLog)? Logger.TryGet(LogEventLevel.Debug, ImeLog)?
.Log(null, "IUITextInput:GetFirstRectForRange"); .Log(null, "IUITextInput:GetFirstRectForRange");
// TODO: Query from the input client // TODO: Query from the input client
@ -377,11 +406,11 @@ partial class AvaloniaView
if (presenter is { }) if (presenter is { })
{ {
var hitResult = presenter.TextLayout.HitTestPoint(new Point(point.X, point.Y)); var hitResult = presenter.TextLayout.HitTestPoint(new Point(point.X, point.Y));
return new AvaloniaTextPosition(hitResult.TextPosition); return new AvaloniaTextPosition(hitResult.TextPosition);
} }
return null; return EmptyPosition;
} }
UITextPosition IUITextInput.GetClosestPositionToPoint(CGPoint point, UITextRange withinRange) UITextPosition IUITextInput.GetClosestPositionToPoint(CGPoint point, UITextRange withinRange)
@ -440,7 +469,7 @@ partial class AvaloniaView
NSDictionary? IUITextInput.MarkedTextStyle NSDictionary? IUITextInput.MarkedTextStyle
{ {
get => null; get => null;
set {} set { }
} }
UITextPosition IUITextInput.BeginningOfDocument => _beginningOfDocument; UITextPosition IUITextInput.BeginningOfDocument => _beginningOfDocument;
@ -478,7 +507,7 @@ partial class AvaloniaView
var res = base.ResignFirstResponder(); var res = base.ResignFirstResponder();
if (res && ReferenceEquals(CurrentAvaloniaResponder, this)) if (res && ReferenceEquals(CurrentAvaloniaResponder, this))
{ {
Logger.TryGet(LogEventLevel.Debug, "IOSIME") Logger.TryGet(LogEventLevel.Debug, "IOSIME")
?.Log(null, "Resigned first responder"); ?.Log(null, "Resigned first responder");
_client.SurroundingTextChanged -= SurroundingTextChanged; _client.SurroundingTextChanged -= SurroundingTextChanged;

Loading…
Cancel
Save