private static DataPackageView GetFromNative(NSPasteboard pasteboard) { if (pasteboard is null) { throw new ArgumentException(nameof(pasteboard)); } var dataPackage = new DataPackage(); var clipHtml = pasteboard.GetStringForType(NSPasteboard.NSPasteboardTypeHTML); if (clipHtml != null) { dataPackage.SetHtmlFormat(clipHtml); } var clipRtf = pasteboard.GetStringForType(NSPasteboard.NSPasteboardTypeRTF); if (clipRtf != null) { dataPackage.SetRtf(clipRtf); } var clipText = pasteboard.GetStringForType(NSPasteboard.NSPasteboardTypeString); if (clipText != null) { dataPackage.SetText(clipText); } return(dataPackage.GetView()); }
private static async Task <bool> ShowShareUIAsync(ShareUIOptions options, DataPackage dataPackage) { var dataPackageView = dataPackage.GetView(); var title = dataPackage.Properties.Title != null ? $"\"{WebAssemblyRuntime.EscapeJs(dataPackage.Properties.Title)}\"" : null; string?text; if (dataPackageView.Contains(StandardDataFormats.Text)) { text = await dataPackageView.GetTextAsync(); } else { text = dataPackage.Properties.Description; } text = text != null ? $"\"{WebAssemblyRuntime.EscapeJs(text)}\"" : null; var uri = await GetSharedUriAsync(dataPackageView); var uriText = uri != null ? $"\"{WebAssemblyRuntime.EscapeJs(uri.OriginalString)}\"" : null; var result = await WebAssemblyRuntime.InvokeAsync($"{JsType}.showShareUI({title ?? "null"},{text ?? "null"},{uriText ?? "null"})"); return(bool.TryParse(result, out var boolResult) && boolResult); }
public static DataPackageView GetContent() { var dataPackage = new DataPackage(); dataPackage.SetDataProvider(StandardDataFormats.Text, async ct => await GetClipboardText(ct)); return(dataPackage.GetView()); }
private static async Task <bool> ShowShareUIAsync(ShareUIOptions options, DataPackage dataPackage) { var window = NSApplication.SharedApplication.MainWindow; if (window == null) { throw new InvalidOperationException("Sharing is not possible when no window is active."); } var view = window.ContentView; var dataPackageView = dataPackage.GetView(); var sharedData = new List <NSObject>(); if (dataPackageView.Contains(StandardDataFormats.Text)) { var text = await dataPackageView.GetTextAsync(); sharedData.Add(new NSString(text)); } var uri = await GetSharedUriAsync(dataPackageView); if (uri != null) { sharedData.Add(NSUrl.FromString(uri.OriginalString)); } CGRect targetRect; if (options.SelectionRect != null) { targetRect = options.SelectionRect.Value; } else { // Try to center the picker within the window targetRect = new CGRect( view.Bounds.Width / 2f - DefaultPickerWidth / 2, view.Bounds.Height / 2 - DefaultPickerHeight / 2, 0, 0); } var picker = new NSSharingServicePicker(sharedData.ToArray()); var completionSource = new TaskCompletionSource <bool>(); picker.DidChooseSharingService += (s, e) => { completionSource.SetResult(e.Service != null); }; picker.ShowRelativeToRect(targetRect, view, NSRectEdge.MinYEdge); return(await completionSource.Task); }
public void Properties_Title_SettingValueThrowsException() { DataPackage dataPackage = new DataPackage(); SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); var e = Assert.Throws<InvalidOperationException>(() => sharePackage.Properties.Description = "Test Value"); Assert.Equal("Cannot modify share properties as a share target.", e.Message); }
public void Properties_Title_GetsValueFromDataPackageView() { DataPackage dataPackage = new DataPackage(); dataPackage.Properties.Title = "Test Value"; SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); Assert.Equal("Test Value", sharePackage.Properties.Title); }
public void Properties_Description_GetsValueFromDataPackageView() { DataPackage dataPackage = new DataPackage(); dataPackage.Properties.Description = "Test Value"; SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); Assert.Equal("Test Value", sharePackage.Properties.Description); }
public async Task SetData_SetsDataOnDataPackage() { DataPackage dataPackage = new DataPackage(); SharePackage sharePackage = new SharePackage(dataPackage); sharePackage.SetData<string>("Test Format", "Test Value"); object data = await dataPackage.GetView().GetDataAsync("Test Format"); Assert.Equal("Test Value", data); }
internal static async Task SetContentAsync(DataPackage /* ? */ content) { var data = content?.GetView(); // Freezes the DataPackage if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); SetClipboardText(text); } }
public void AvailableFormats_ReturnsValuesFromDataPackageView() { DataPackage dataPackage = new DataPackage(); dataPackage.SetData("Format A", "Some data"); dataPackage.SetData("Format B", "Some data"); SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); Assert.Equal(2, sharePackage.AvailableFormats.Count); Assert.Contains("Format A", sharePackage.AvailableFormats.ToList()); Assert.Contains("Format B", sharePackage.AvailableFormats.ToList()); }
internal static async Task SetContentAsync(DataPackage content) { var data = content?.GetView(); // Freezes the DataPackage if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); // Setting to null doesn't reset the clipboard like for Android UIPasteboard.General.String = text ?? string.Empty; } }
public static DataPackageView GetContent() { var dataPackage = new DataPackage(); var clipText = UIPasteboard.General.String; if (clipText != null) { dataPackage.SetText(clipText); } return(dataPackage.GetView()); }
private static async Task <bool> ShowShareUIAsync(ShareUIOptions options, DataPackage dataPackage) { var context = ContextHelper.Current; if (context == null) { if (_instance.Value.Log().IsEnabled(LogLevel.Error)) { _instance.Value.Log().LogError("The Share API was called too early in the application lifecycle"); } return(false); } var dataPackageView = dataPackage.GetView(); var items = new List <string>(); if (dataPackageView.Contains(StandardDataFormats.Text)) { var text = await dataPackageView.GetTextAsync(); items.Add(text); } var uri = await GetSharedUriAsync(dataPackageView); if (uri != null) { items.Add(uri.OriginalString); } var intent = new Intent(Intent.ActionSend); intent.SetType("text/plain"); intent.PutExtra(Intent.ExtraText, string.Join(Environment.NewLine, items)); var title = dataPackage.Properties.Title; if (!string.IsNullOrWhiteSpace(title)) { intent.PutExtra(Intent.ExtraSubject, title); } var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty); var flags = ActivityFlags.ClearTop | ActivityFlags.NewTask; chooserIntent?.SetFlags(flags); ContextHelper.Current.StartActivity(chooserIntent); return(true); }
public async Task SetAsyncData_SetsDataOnDataPackage() { DataPackage dataPackage = new DataPackage(); SharePackage sharePackage = new SharePackage(dataPackage); sharePackage.SetAsyncData("Test Format", async (state) => { await Task.Delay(200); return "Test Value"; }); object data = await dataPackage.GetView().GetDataAsync("Test Format"); Assert.Equal("Test Value", data); }
public async Task SetAsyncDataProvider_ReturnsValueFromSyncTask() { DataPackage dataPackage = new DataPackage(); dataPackage.SetAsyncDataProvider(StandardDataFormats.Text, (formatId, deadline) => { return Task.FromResult<object>("Test text"); }); DataPackageView dataPackageView = dataPackage.GetView(); string result = await dataPackageView.GetTextAsync(); Assert.AreEqual("Test text", result); }
public async Task SetAsyncDataProvider_ReturnsValueFromAsyncTask() { DataPackage dataPackage = new DataPackage(); dataPackage.SetAsyncDataProvider(StandardDataFormats.Text, async (formatId, deadline) => { await Task.Delay(200); return "Test text"; }); DataPackageView dataPackageView = dataPackage.GetView(); string result = await dataPackageView.GetTextAsync(); Assert.AreEqual("Test text", result); }
public async Task SetAsyncDataProvider_PassesFormatIdToMethod() { DataPackage dataPackage = new DataPackage(); string formatIdValue = null; dataPackage.SetAsyncDataProvider(StandardDataFormats.Text, (formatId, deadline) => { formatIdValue = formatId; return Task.FromResult<object>("Test text"); }); DataPackageView dataPackageView = dataPackage.GetView(); string result = await dataPackageView.GetTextAsync(); Assert.AreEqual(StandardDataFormats.Text, formatIdValue); }
public async Task SetAsyncDataProvider_PassesDeadlineToMethod() { DataPackage dataPackage = new DataPackage(); DateTimeOffset deadlineValue = DateTimeOffset.MinValue; dataPackage.SetAsyncDataProvider(StandardDataFormats.Text, (formatId, deadline) => { deadlineValue = deadline; return Task.FromResult<object>("Test text"); }); DataPackageView dataPackageView = dataPackage.GetView(); string result = await dataPackageView.GetTextAsync(); Assert.AreNotEqual(DateTimeOffset.MinValue, deadlineValue); }
public static DataPackageView GetContent() { var dataPackage = new DataPackage(); dataPackage.SetDataProvider( StandardDataFormats.Text, async ct => { var text = string.Empty; await CoreDispatcher.Main.RunAsync( CoreDispatcherPriority.High, async _ => text = await GetClipboardText()); return(text); }); return(dataPackage.GetView()); }
public async Task SetAsyncStorageItems_ReturnsValueFromAsyncTask() { DataPackage dataPackage = new DataPackage(); StorageFile file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("Test file.xml"); dataPackage.SetAsyncStorageItems(async (formatId, deadline) => { await Task.Delay(200); return new IStorageItem[] { file }; }); DataPackageView dataPackageView = dataPackage.GetView(); IReadOnlyList<IStorageItem> result = await dataPackageView.GetStorageItemsAsync(); Assert.AreEqual(1, result.Count); Assert.AreEqual(file.Path, result[0].Path); }
public async Task SetAsyncRtf_ReturnsValueFromAsyncTask() { DataPackage dataPackage = new DataPackage(); dataPackage.SetAsyncRtf(async (formatId, deadline) => { await Task.Delay(200); return "Test RTF"; }); DataPackageView dataPackageView = dataPackage.GetView(); string result = await dataPackageView.GetRtfAsync(); Assert.AreEqual("Test RTF", result); }
public void Contains_ThrowsException_IfFormatIdIsNull() { DataPackage dataPackage = new DataPackage(); dataPackage.SetData("Format A", "Some data"); dataPackage.SetData("Format B", "Some data"); SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); var e = Assert.Throws<ArgumentException>(() => sharePackage.Contains(null)); Assert.Equal("The argument cannot be null or an empty string.\r\nParameter name: formatId", e.Message); Assert.Equal("formatId", e.ParamName); }
public async Task ShareRequested() { // Arrange var viewModel = GetViewModel(); var dataPackage = new DataPackage(); var dataPackageView = dataPackage.GetView(); var feedItem = new FeedItem { Title = Guid.NewGuid().ToString(), Author = Guid.NewGuid().ToString(), Link = new Uri("http://www.bing.com") }; viewModel.LoadState(feedItem, null); // Act this.ShareManager.OnShareRequested(dataPackage); // Assert Assert.IsFalse(string.IsNullOrEmpty(await dataPackageView.GetTextAsync()), "Text Exists"); Assert.AreEqual(feedItem.Link.ToString(), (await dataPackageView.GetUriAsync()).ToString(), "Uri"); Assert.IsTrue(!string.IsNullOrEmpty(await dataPackageView.GetHtmlFormatAsync()), "HTML Exists"); }
private static async Task SetToNativeAsync(DataPackage content, NSPasteboard pasteboard) { if (pasteboard is null) { throw new ArgumentException(nameof(pasteboard)); } var data = content?.GetView(); var declaredTypes = new List <string>(); string?uri = null; /* Note that order is somewhat important here. * * According to the docs: * "types should be ordered according to the preference of the source application, * with the most preferred type coming first" * https://developer.apple.com/documentation/appkit/nspasteboard/1533561-declaretypes?language=objc * * This means we want to process certain types like HTML/RTF before general plain text * as they are more specific. * * Types are also declared before setting */ // Declare types if (data?.Contains(StandardDataFormats.Html) ?? false) { declaredTypes.Add(NSPasteboard.NSPasteboardTypeHTML); } if (data?.Contains(StandardDataFormats.Rtf) ?? false) { // Use `NSPasteboardTypeRTF` instead of `NSPasteboardTypeRTFD` for max compatibility declaredTypes.Add(NSPasteboard.NSPasteboardTypeRTF); } if (data?.Contains(StandardDataFormats.Text) ?? false) { declaredTypes.Add(NSPasteboard.NSPasteboardTypeString); } if (data != null) { uri = DataPackage.CombineUri( data.Contains(StandardDataFormats.WebLink) ? (await data.GetWebLinkAsync()).ToString() : null, data.Contains(StandardDataFormats.ApplicationLink) ? (await data.GetApplicationLinkAsync()).ToString() : null, data.Contains(StandardDataFormats.Uri) ? (await data.GetUriAsync()).ToString() : null); if (string.IsNullOrEmpty(uri) == false) { declaredTypes.Add(NSPasteboard.NSPasteboardTypeUrl); } } pasteboard.DeclareTypes(declaredTypes.ToArray(), null); // Set content if (data?.Contains(StandardDataFormats.Html) ?? false) { var html = await data.GetHtmlFormatAsync(); pasteboard.SetStringForType(html ?? string.Empty, NSPasteboard.NSPasteboardTypeHTML); } if (data?.Contains(StandardDataFormats.Rtf) ?? false) { var rtf = await data.GetRtfAsync(); pasteboard.SetStringForType(rtf ?? string.Empty, NSPasteboard.NSPasteboardTypeRTF); } if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); pasteboard.SetStringForType(text ?? string.Empty, NSPasteboard.NSPasteboardTypeString); } if (string.IsNullOrEmpty(uri) == false) { pasteboard.SetStringForType(uri !.ToString(), NSPasteboard.NSPasteboardTypeUrl); } return; }
public async Task SharePoll() { // Arrange var viewModel = GetViewModel(); var random = new Random(); var principal = new PrincipalMock(); var identity = new UserIdentityMock(); identity.UserID = random.Next(); principal.Identity = identity; Csla.ApplicationContext.User = principal; var pollId = random.Next(); var pollSubmission = new PollSubmissionMock { PollID = pollId }; ObjectFactory.CreateAsyncDelegate = () => new PollSubmissionCommandMock(); ObjectFactory.ExecuteAsyncDelegate = (command) => { return new PollSubmissionCommandMock { Submission = pollSubmission }; }; var wasShareManagerInitialized = false; ShareManager.InitializeDelegate = () => { wasShareManagerInitialized = true; }; viewModel.Parameter = Serializer.Serialize( new ViewPollPageNavigationCriteria { PollId = pollId }); await viewModel.LoadPollAsync(); ((IActivate)viewModel).Activate(); var dataPackage = new DataPackage(); var dataPackageView = dataPackage.GetView(); // Act ShareManager.ExecuteShareRequested(dataPackage); // Assert Assert.IsTrue(wasShareManagerInitialized, "Was Share Manager Initialized"); Assert.IsTrue(!string.IsNullOrEmpty(await dataPackageView.GetTextAsync()), "Text Exists"); Assert.AreEqual(string.Format("myvote://poll/{0}", pollId), (await dataPackageView.GetApplicationLinkAsync()).ToString(), "Uri"); Assert.IsTrue(!string.IsNullOrEmpty(await dataPackageView.GetHtmlFormatAsync()), "HTML Exists"); }
private static async Task <bool> ShowShareUIAsync(ShareUIOptions options, DataPackage dataPackage) { var rootViewController = UIApplication.SharedApplication?.KeyWindow?.RootViewController; if (rootViewController == null) { if (_instance.Value.Log().IsEnabled(LogLevel.Error)) { _instance.Value.Log().LogError("The Share API was called too early in the application lifecycle"); } return(false); } var dataPackageView = dataPackage.GetView(); var sharedData = new List <NSObject>(); var title = dataPackage.Properties.Title ?? string.Empty; if (dataPackageView.Contains(StandardDataFormats.Text)) { var text = await dataPackageView.GetTextAsync(); sharedData.Add(new DataActivityItemSource(new NSString(text), title)); } var uri = await GetSharedUriAsync(dataPackageView); if (uri != null) { sharedData.Add(new DataActivityItemSource(NSUrl.FromString(uri.OriginalString), title)); } var activityViewController = new UIActivityViewController(sharedData.ToArray(), null); if (activityViewController.PopoverPresentationController != null && rootViewController.View != null) { activityViewController.PopoverPresentationController.SourceView = rootViewController.View; if (options.SelectionRect != null) { activityViewController.PopoverPresentationController.SourceRect = options.SelectionRect.Value.ToCGRect(); } else { activityViewController.PopoverPresentationController.SourceRect = new CGRect(rootViewController.View.Bounds.Width / 2, rootViewController.View.Bounds.Height / 2, 0, 0); activityViewController.PopoverPresentationController.PermittedArrowDirections = 0; } } if (options.Theme != ShareUITheme.Default) { activityViewController.OverrideUserInterfaceStyle = options.Theme == ShareUITheme.Light ? UIUserInterfaceStyle.Light : UIUserInterfaceStyle.Dark; } else { // Theme should match the application theme activityViewController.OverrideUserInterfaceStyle = CoreApplication.RequestedTheme == SystemTheme.Light ? UIUserInterfaceStyle.Light : UIUserInterfaceStyle.Dark; } var completionSource = new TaskCompletionSource <bool>(); activityViewController.CompletionWithItemsHandler = (NSString activityType, bool completed, NSExtensionItem[] returnedItems, NSError error) => { completionSource.SetResult(completed); }; await rootViewController.PresentViewControllerAsync(activityViewController, true); return(await completionSource.Task); }
public async Task SharePoll() { // Arrange var viewModel = GetViewModel(); var random = new Random(); var pollId = random.Next(); var pollDataResults = new PollDataResultsMock { PollID = pollId, Question = Guid.NewGuid().ToString() }; pollDataResults.ResultsDelegate = () => { return new ReadOnlyListBaseCoreMock<IPollDataResult>(new List<IPollDataResult>()); }; var pollResults = new PollResultsMock { PollID = pollId, PollDataResults = pollDataResults }; Csla.ApplicationContext.User = new PrincipalMock { Identity = new UserIdentityMock { UserID = random.Next() } }; int actualPollId = -1; ObjectFactory.FetchAsyncWithCriteriaDelegate = (criteria) => { actualPollId = ((PollResultsCriteria)criteria).PollID; return pollResults; }; var wasShareManagerInitialized = false; ShareManager.InitializeDelegate = () => { wasShareManagerInitialized = true; }; viewModel.Parameter = Serializer.Serialize( new PollResultsPageNavigationCriteria { PollId = pollId }); await viewModel.LoadPollAsync(); ((IActivate)viewModel).Activate(); var dataPackage = new DataPackage(); var dataPackageView = dataPackage.GetView(); // Act ShareManager.ExecuteShareRequested(dataPackage); // Assert Assert.IsTrue(wasShareManagerInitialized, "Was Share Manager Initialized"); Assert.AreEqual(pollId, actualPollId, "Actual Poll Id"); Assert.IsTrue(!string.IsNullOrEmpty(await dataPackageView.GetTextAsync()), "Text Exists"); Assert.AreEqual(string.Format("myvote://poll/{0}", pollId), (await dataPackageView.GetApplicationLinkAsync()).ToString(), "Uri"); Assert.IsTrue(!string.IsNullOrEmpty(await dataPackageView.GetHtmlFormatAsync()), "HTML Exists"); }
internal static async Task SetContentAsync(DataPackage content) { var data = content?.GetView(); var items = new List <ClipData.Item>(); var mimeTypes = new List <string>(); if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); items.Add(new ClipData.Item(text)); mimeTypes.Add("text/plaintext"); } // UWP has the following standard data formats that correspond with an Android Uri: // // 1. Uri, now deprecated in favor of: // 2. ApplicationLink and // 3. WebLink // // For maximum compatibility with Android all are mapped to Uri. However, only // one may be used at a time in the above defined priority. WebLink is // considered more specific than ApplicationLink. if (data?.Contains(StandardDataFormats.Uri) ?? false) { var uri = await data.GetUriAsync(); AddAndroidUri(uri.ToString()); } else if (data?.Contains(StandardDataFormats.WebLink) ?? false) { var webLink = await data.GetWebLinkAsync(); AddAndroidUri(webLink.ToString()); } else if (data?.Contains(StandardDataFormats.ApplicationLink) ?? false) { var appLink = await data.GetApplicationLinkAsync(); AddAndroidUri(appLink.ToString()); } if (data?.Contains(StandardDataFormats.Html) ?? false) { var html = await data.GetHtmlFormatAsync(); // Matches all tags Regex regex = new Regex("(<.*?>\\s*)+", RegexOptions.Singleline); // Replace tags by spaces and trim var plainText = regex.Replace(html, " ").Trim(); items.Add(new ClipData.Item(plainText, html)); mimeTypes.Add("text/html"); } // Set all the data formats to the Android clipboard if (items.Count > 0) { ClipData clipData = new ClipData( new ClipDescription(ClipboardDataLabel, mimeTypes.ToArray()), items[0]); for (int itemIndex = 1; itemIndex < items.Count; itemIndex++) { clipData.AddItem(items[itemIndex]); } var manager = ContextHelper.Current.GetSystemService(Context.ClipboardService) as ClipboardManager; if (manager is null) { return; } manager.PrimaryClip = clipData; } else { // Clear clipboard Clear(); } // Local function to convert a UWP Uri for Android and add it to the items list void AddAndroidUri(string uri) { var androidUri = Android.Net.Uri.Parse(uri); items.Add(new ClipData.Item(androidUri)); mimeTypes.Add("text/uri-list"); } }
public static DataPackageView GetContent() { var dataPackage = new DataPackage(); var manager = ContextHelper.Current.GetSystemService(Context.ClipboardService) as ClipboardManager; if (manager is null) { return(dataPackage.GetView()); } var clipData = manager.PrimaryClip; Uri /* ? */ clipApplicationLink = null; string /* ? */ clipHtml = null; string /* ? */ clipText = null; Uri /* ? */ clipUri = null; Uri /* ? */ clipWebLink = null; // Extract all the standard data format information from the clipboard. // Each format can only be used once; therefore, the last occurrence of the format will be the one used. if (clipData != null) { for (int itemIndex = 0; itemIndex < clipData.ItemCount; itemIndex++) { var item = clipData.GetItemAt(itemIndex); if (item != null) { var itemText = item.Text; if (itemText != null) { clipText = itemText; } // An Android Uri must be specially mapped for UWP as the UWP's direct equivalent // standard data format 'Uri' is deprecated. // // 1. WebLink is used if the URI has a scheme of http or https // 2. ApplicationLink is used if not #1 // // For full compatibility, Uri is still populated regardless of #1 or #2. var itemUri = item.Uri; var itemUriStr = itemUri?.ToString(); if (itemUriStr != null) { if (itemUriStr.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) || itemUriStr.StartsWith("https", StringComparison.InvariantCultureIgnoreCase)) { clipWebLink = new Uri(itemUriStr); } else { clipApplicationLink = new Uri(itemUriStr); } // Deprecated but added for compatibility clipUri = new Uri(itemUriStr); } var itemHtml = item.HtmlText; if (itemText != null) { clipHtml = itemHtml; } } } } // Add standard data formats to the data package. // This can be done synchronously on Android since the data is already available from above. if (clipApplicationLink != null) { dataPackage.SetApplicationLink(clipApplicationLink); } if (clipHtml != null) { dataPackage.SetHtmlFormat(clipHtml); } if (clipText != null) { dataPackage.SetText(clipText); } if (clipUri != null) { dataPackage.SetUri(clipUri); } if (clipWebLink != null) { dataPackage.SetWebLink(clipWebLink); } return(dataPackage.GetView()); }
public async void GetDataAsync_ThrowsException_IfFormatIdIsEmpty() { DataPackage dataPackage = new DataPackage(); dataPackage.SetData("Format A", "Some data"); dataPackage.SetData("Format B", "Some data"); SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); var e = await Assert.ThrowsAsync<ArgumentException>(() => sharePackage.GetDataAsync<string>("")); Assert.Equal("The argument cannot be null or an empty string.\r\nParameter name: formatId", e.Message); Assert.Equal("formatId", e.ParamName); }
public async Task SetAsyncUri_ReturnsValueFromAsyncTask() { DataPackage dataPackage = new DataPackage(); dataPackage.SetAsyncUri(async (formatId, deadline) => { await Task.Delay(200); return new Uri("http://www.example.org/"); }); DataPackageView dataPackageView = dataPackage.GetView(); Uri result = await dataPackageView.GetUriAsync(); Assert.AreEqual("http://www.example.org/", result.AbsoluteUri); }
private static DataPackageView GetFromNative(NSPasteboard pasteboard) { if (pasteboard is null) { throw new ArgumentException(nameof(pasteboard)); } var dataPackage = new DataPackage(); // Extract all the standard data format information from the pasteboard items. // Each format can only be used once; therefore, generally the last occurrence of the format will be the one used. foreach (NSPasteboardItem item in pasteboard.PasteboardItems) { if (item.Types.Contains(NSPasteboard.NSPasteboardTypeTIFF) || item.Types.Contains(NSPasteboard.NSPasteboardTypePNG)) { // Images may be very large, we never want to load them until they are needed. // Therefore, create a data provider used to asynchronously fetch the image. dataPackage.SetDataProvider( StandardDataFormats.Bitmap, async cancellationToken => { NSImage?image = null; /* Some apps, including Photos, don't appear to put image data in the pasteboard. * Instead, the image URL is provided although the type indicates it is an image. * * To get around this an image is read as follows: * (1) If the pasteboard contains an image type then: * (2) Attempt to read the image as an object (NSImage). * This may fail as some tested apps provide a URL although declare an image (Photos). * With other apps (such as web browsers) an image will be read correctly here. * (3) If reading as an NSImage object fails, attempt to read the image from a file URL (local images) * (4) If reading from a file URL fails, attempt to read the image from a URL (remote images) * * Reading as an NSImage object follows the docs here: * https://docs.microsoft.com/en-us/xamarin/mac/app-fundamentals/copy-paste#add-an-nsdocument */ var classArray = new Class[] { new Class("NSImage") }; if (pasteboard.CanReadObjectForClasses(classArray, null)) { NSObject[] objects = pasteboard.ReadObjectsForClasses(classArray, null); if (objects.Length > 0) { // Only use the first image found image = objects[0] as NSImage; } } // In order to get here the pasteboard must have declared it had image types. // However, if image is null, no objects were found and the image is likely a URL instead. if (image == null && item.Types.Contains(NSPasteboard.NSPasteboardTypeFileUrl)) { var url = item.GetStringForType(NSPasteboard.NSPasteboardTypeFileUrl); image = new NSImage(new NSUrl(url)); } if (image == null && item.Types.Contains(NSPasteboard.NSPasteboardTypeUrl)) { var url = item.GetStringForType(NSPasteboard.NSPasteboardTypeUrl); image = new NSImage(new NSUrl(url)); } if (image != null) { // Thanks to: https://stackoverflow.com/questions/13305028/monomac-best-way-to-convert-bitmap-to-nsimage/13355747 using (var imageData = image.AsTiff()) { var imgRep = NSBitmapImageRep.ImageRepFromData(imageData !) as NSBitmapImageRep; var data = imgRep !.RepresentationUsingTypeProperties(NSBitmapImageFileType.Png, null); return(new RandomAccessStreamReference(async ct => { return data.AsStream().AsRandomAccessStream().TrySetContentType("image/png"); })); } } else { // Return an empty image return(new RandomAccessStreamReference(async ct => { var stream = new MemoryStream(); stream.Position = 0; return stream.AsRandomAccessStream().TrySetContentType("image/png"); })); } }); } if (item.Types.Contains(NSPasteboard.NSPasteboardTypeHTML)) { var html = item.GetStringForType(NSPasteboard.NSPasteboardTypeHTML); if (html != null) { dataPackage.SetHtmlFormat(html); } } if (item.Types.Contains(NSPasteboard.NSPasteboardTypeRTF)) { var rtf = item.GetStringForType(NSPasteboard.NSPasteboardTypeRTF); if (rtf != null) { dataPackage.SetRtf(rtf); } } if (item.Types.Contains(NSPasteboard.NSPasteboardTypeFileUrl)) { // Drag and drop will use temporary URLs similar to: file:///.file/id=1234567.1234567 var tempFileUrl = item.GetStringForType(NSPasteboard.NSPasteboardTypeFileUrl); // Files may be very large, we never want to load them until they are needed. // Therefore, create a data provider used to asynchronously fetch the file. dataPackage.SetDataProvider( StandardDataFormats.StorageItems, async cancellationToken => { // Convert from a temp Url (see above example) into an absolute file path var fileUrl = new NSUrl(tempFileUrl); var file = await StorageFile.GetFileFromPathAsync(fileUrl.FilePathUrl.AbsoluteString); var storageItems = new List <IStorageItem>(); storageItems.Add(file); return(storageItems.AsReadOnly()); }); } if (item.Types.Contains(NSPasteboard.NSPasteboardTypeString)) { var text = item.GetStringForType(NSPasteboard.NSPasteboardTypeString); if (text != null) { dataPackage.SetText(text); } } if (item.Types.Contains(NSPasteboard.NSPasteboardTypeUrl)) { var url = item.GetStringForType(NSPasteboard.NSPasteboardTypeUrl); if (url != null) { DataPackage.SeparateUri( url, out string?webLink, out string?applicationLink); if (webLink != null) { dataPackage.SetWebLink(new Uri(webLink)); } if (applicationLink != null) { dataPackage.SetApplicationLink(new Uri(applicationLink)); } // Deprecated but still added for compatibility dataPackage.SetUri(new Uri(url)); } } } return(dataPackage.GetView()); }
private static async Task SetToNativeAsync(DataPackage content, NSPasteboard pasteboard) { if (pasteboard is null) { throw new ArgumentException(nameof(pasteboard)); } var data = content?.GetView(); var declaredTypes = new List <string>(); // Note that order is somewhat important here. // // According to the docs: // "types should be ordered according to the preference of the source application, // with the most preferred type coming first" // https://developer.apple.com/documentation/appkit/nspasteboard/1533561-declaretypes?language=objc // // This means we want to process certain types like HTML/RTF before general plain text // as they are more specific. // Types are also declared before setting // Declare types if (data?.Contains(StandardDataFormats.Html) ?? false) { declaredTypes.Add(NSPasteboard.NSPasteboardTypeHTML); } if (data?.Contains(StandardDataFormats.Rtf) ?? false) { // Use `NSPasteboardTypeRTF` instead of `NSPasteboardTypeRTFD` for max compatiblity declaredTypes.Add(NSPasteboard.NSPasteboardTypeRTF); } if (data?.Contains(StandardDataFormats.Text) ?? false) { declaredTypes.Add(NSPasteboard.NSPasteboardTypeString); } pasteboard.DeclareTypes(declaredTypes.ToArray(), null); // Set content if (data?.Contains(StandardDataFormats.Html) ?? false) { var html = await data.GetHtmlFormatAsync(); pasteboard.SetStringForType(html ?? string.Empty, NSPasteboard.NSPasteboardTypeHTML); } if (data?.Contains(StandardDataFormats.Rtf) ?? false) { var rtf = await data.GetRtfAsync(); pasteboard.SetStringForType(rtf ?? string.Empty, NSPasteboard.NSPasteboardTypeRTF); } if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); pasteboard.SetStringForType(text ?? string.Empty, NSPasteboard.NSPasteboardTypeString); } }
public async Task GetDataAsync_GetsDataFromDataPackage() { DataPackage dataPackage = new DataPackage(); dataPackage.SetData("Test Format", "Test Value"); SharePackageView sharePackageView = new SharePackageView(dataPackage.GetView()); string data = await sharePackageView.GetDataAsync<string>("Test Format"); Assert.Equal("Test Value", data); }
public static DataPackageView GetContent() { var dataPackage = new DataPackage(); var manager = ContextHelper.Current.GetSystemService(Context.ClipboardService) as ClipboardManager; if (manager is null) { return(dataPackage.GetView()); } var clipData = manager.PrimaryClip; Uri /* ? */ clipApplicationLink = null; string /* ? */ clipHtml = null; string /* ? */ clipText = null; Uri /* ? */ clipUri = null; Uri /* ? */ clipWebLink = null; // Extract all the standard data format information from the clipboard. // Each format can only be used once; therefore, the last occurrence of the format will be the one used. if (clipData != null) { for (int itemIndex = 0; itemIndex < clipData.ItemCount; itemIndex++) { var item = clipData.GetItemAt(itemIndex); if (item != null) { var itemText = item.Text; if (itemText != null) { clipText = itemText; } var itemUriStr = item.Uri?.ToString(); if (itemUriStr != null) { DataPackage.SeparateUri( itemUriStr, out string webLink, out string applicationLink); clipWebLink = webLink != null ? new Uri(webLink) : null; clipApplicationLink = applicationLink != null ? new Uri(applicationLink) : null; clipUri = new Uri(itemUriStr); // Deprecated but still added for compatibility } var itemHtml = item.HtmlText; if (itemHtml != null) { clipHtml = itemHtml; } } } } // Add standard data formats to the data package. // This can be done synchronously on Android since the data is already available from above. if (clipApplicationLink != null) { dataPackage.SetApplicationLink(clipApplicationLink); } if (clipHtml != null) { dataPackage.SetHtmlFormat(clipHtml); } if (clipText != null) { dataPackage.SetText(clipText); } if (clipUri != null) { dataPackage.SetUri(clipUri); } if (clipWebLink != null) { dataPackage.SetWebLink(clipWebLink); } return(dataPackage.GetView()); }
public void Contains_ReturnsFalseIfFormatIsNotAvailable() { DataPackage dataPackage = new DataPackage(); dataPackage.SetData("Format A", "Some data"); dataPackage.SetData("Format B", "Some data"); SharePackageView sharePackage = new SharePackageView(dataPackage.GetView()); Assert.False(sharePackage.Contains("Format C")); }
public async Task SetAsyncBitmap_ReturnsValueFromAsyncTask() { DataPackage dataPackage = new DataPackage(); RandomAccessStreamReference streamRef = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Images/UnitTestLogo.png")); dataPackage.SetAsyncBitmap(async (formatId, deadline) => { await Task.Delay(200); return streamRef; }); DataPackageView dataPackageView = dataPackage.GetView(); RandomAccessStreamReference result = await dataPackageView.GetBitmapAsync(); Assert.AreEqual(streamRef, result); }
internal static async Task SetContentAsync(DataPackage content) { var data = content?.GetView(); var items = new List <ClipData.Item>(); var mimeTypes = new List <string>(); if (data?.Contains(StandardDataFormats.Text) ?? false) { var text = await data.GetTextAsync(); items.Add(new ClipData.Item(text)); mimeTypes.Add("text/plaintext"); } if (data != null) { var uri = DataPackage.CombineUri( data.Contains(StandardDataFormats.WebLink) ? (await data.GetWebLinkAsync()).ToString() : null, data.Contains(StandardDataFormats.ApplicationLink) ? (await data.GetApplicationLinkAsync()).ToString() : null, data.Contains(StandardDataFormats.Uri) ? (await data.GetUriAsync()).ToString() : null); if (string.IsNullOrEmpty(uri) == false) { var androidUri = Android.Net.Uri.Parse(uri); items.Add(new ClipData.Item(androidUri)); mimeTypes.Add("text/uri-list"); } } if (data?.Contains(StandardDataFormats.Html) ?? false) { var html = await data.GetHtmlFormatAsync(); // Matches all tags Regex regex = new Regex("(<.*?>\\s*)+", RegexOptions.Singleline); // Replace tags by spaces and trim var plainText = regex.Replace(html, " ").Trim(); items.Add(new ClipData.Item(plainText, html)); mimeTypes.Add("text/html"); } // Set all the data formats to the Android clipboard if (items.Count > 0) { ClipData clipData = new ClipData( new ClipDescription(ClipboardDataLabel, mimeTypes.ToArray()), items[0]); for (int itemIndex = 1; itemIndex < items.Count; itemIndex++) { clipData.AddItem(items[itemIndex]); } var manager = ContextHelper.Current.GetSystemService(Context.ClipboardService) as ClipboardManager; if (manager is null) { return; } manager.PrimaryClip = clipData; } else { // Clear clipboard Clear(); } }