Fix compilation: restore clean RC1 codebase
- Restore clean BindableProperty.Create syntax from RC1 commit - Remove decompiler artifacts with mangled delegate types - Add Svg.Skia package reference for icon support - Fix duplicate type definitions - Library now compiles successfully (0 errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,139 +1,147 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Maui.ApplicationModel.DataTransfer;
|
||||
using Microsoft.Maui.Storage;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Linux share implementation using xdg-open and portal APIs.
|
||||
/// </summary>
|
||||
public class ShareService : IShare
|
||||
{
|
||||
public async Task RequestAsync(ShareTextRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException("request");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(request.Uri))
|
||||
{
|
||||
await OpenUrlAsync(request.Uri);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(request.Text))
|
||||
{
|
||||
string text = Uri.EscapeDataString(request.Subject ?? "");
|
||||
string text2 = Uri.EscapeDataString(request.Text ?? "");
|
||||
string url = "mailto:?subject=" + text + "&body=" + text2;
|
||||
await OpenUrlAsync(url);
|
||||
}
|
||||
}
|
||||
public async Task RequestAsync(ShareTextRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
public async Task RequestAsync(ShareFileRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException("request");
|
||||
}
|
||||
if (request.File == null)
|
||||
{
|
||||
throw new ArgumentException("File is required", "request");
|
||||
}
|
||||
await ShareFileAsync(((FileBase)request.File).FullPath);
|
||||
}
|
||||
// On Linux, we can use mailto: for text sharing or write to a temp file
|
||||
if (!string.IsNullOrEmpty(request.Uri))
|
||||
{
|
||||
// Share as URL
|
||||
await OpenUrlAsync(request.Uri);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(request.Text))
|
||||
{
|
||||
// Try to use email for text sharing
|
||||
var subject = Uri.EscapeDataString(request.Subject ?? "");
|
||||
var body = Uri.EscapeDataString(request.Text ?? "");
|
||||
var mailto = $"mailto:?subject={subject}&body={body}";
|
||||
await OpenUrlAsync(mailto);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RequestAsync(ShareMultipleFilesRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException("request");
|
||||
}
|
||||
if (request.Files == null || !request.Files.Any())
|
||||
{
|
||||
throw new ArgumentException("Files are required", "request");
|
||||
}
|
||||
foreach (ShareFile file in request.Files)
|
||||
{
|
||||
await ShareFileAsync(((FileBase)file).FullPath);
|
||||
}
|
||||
}
|
||||
public async Task RequestAsync(ShareFileRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
private async Task OpenUrlAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdg-open",
|
||||
Arguments = "\"" + url + "\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using Process process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception innerException)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to open URL for sharing", innerException);
|
||||
}
|
||||
}
|
||||
if (request.File == null)
|
||||
throw new ArgumentException("File is required", nameof(request));
|
||||
|
||||
private async Task ShareFileAsync(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException("File not found for sharing", filePath);
|
||||
}
|
||||
try
|
||||
{
|
||||
if (await TryPortalShareAsync(filePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdg-open",
|
||||
Arguments = "\"" + Path.GetDirectoryName(filePath) + "\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using Process process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception innerException)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to share file", innerException);
|
||||
}
|
||||
}
|
||||
await ShareFileAsync(request.File.FullPath);
|
||||
}
|
||||
|
||||
private async Task<bool> TryPortalShareAsync(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "zenity",
|
||||
Arguments = $"--info --text=\"File ready to share:\\n{Path.GetFileName(filePath)}\\n\\nPath: {filePath}\" --title=\"Share File\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using Process process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public async Task RequestAsync(ShareMultipleFilesRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.Files == null || !request.Files.Any())
|
||||
throw new ArgumentException("Files are required", nameof(request));
|
||||
|
||||
// Share files one by one or use file manager
|
||||
foreach (var file in request.Files)
|
||||
{
|
||||
await ShareFileAsync(file.FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenUrlAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdg-open",
|
||||
Arguments = $"\"{url}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using var process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to open URL for sharing", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ShareFileAsync(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("File not found for sharing", filePath);
|
||||
|
||||
try
|
||||
{
|
||||
// Try to use the portal API via gdbus for proper share dialog
|
||||
var portalResult = await TryPortalShareAsync(filePath);
|
||||
if (portalResult)
|
||||
return;
|
||||
|
||||
// Fall back to opening with default file manager
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdg-open",
|
||||
Arguments = $"\"{Path.GetDirectoryName(filePath)}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using var process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to share file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> TryPortalShareAsync(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try freedesktop portal for proper share dialog
|
||||
// This would use org.freedesktop.portal.FileChooser or similar
|
||||
// For now, we'll use zenity --info as a fallback notification
|
||||
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "zenity",
|
||||
Arguments = $"--info --text=\"File ready to share:\\n{Path.GetFileName(filePath)}\\n\\nPath: {filePath}\" --title=\"Share File\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using var process = Process.Start(startInfo);
|
||||
if (process != null)
|
||||
{
|
||||
await process.WaitForExitAsync();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user