Skip to content

Commit 9bda6c3

Browse files
Android Version (#167)
* Move all UI to MainView; NuGet update; Avalonia Shell init * Move to ReactiveUI * Working modal opening; Weird navbar bug * SideMenu hide * PixedWindow for sub windows base * AboutWindow as PixedWindow * PixedWindow now can return values; GridSettingsWindow is extending PixedWindow class * Reimplement Windows to use PixedWindow * WIP Android project; IPlatformFolder for getting pixed folder; Move DialogUtils to DI * IApplicationLifecycle now for closing app; Set default platform folder * VS Cleanup * Working android project; Absolute folder path for C# IO operations and IStorageFolder for IStorageProvider * Zoom to PaintCanvas size on resize * Move routing to separate namespace; Route class * MenuItem builder for cross platform * MainView as root for non windows platforms; old MainView renamed to MainPage; App.axaml.cs cleanup; PaintCanvas border fix * Android Icon * QuitCommand fix for Android * Version getting fix for android * Android settings * Styles cleanup * Modern splash screen * Splash screen fix * StreamBase for fixing android stream using * Disable recent files for android * Tool icons in Menu * Fullscreen only for Windows; Id, Name defined in BaseTool; Menu icons * VS Cleanup * Saving file with extension on Android * Save file dialog can have only one format if SingleExtensionSaveDialog is true * Rename IApplicationLifecycle to IPlatformSettings; Adapt implementations to new name * TODO Fixes * Remove single format save dialog functionalities * Cleanup * Force SKColorType for generating SKBitmap from array * Navigation methods for common modals * Restore HandleNewInstance for desktop * Message modal * Palette files as AbstractPaletteSerializer; Loading palettes cleanup * Internal storage IO unified * Transparent background fix * Overlay render don't render on smaller zoom; Transparent background scale relative to screen * Code cleanup * Nuget update
1 parent 0f89982 commit 9bda6c3

File tree

209 files changed

+2793
-1423
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+2793
-1423
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
33
<Nullable>enable</Nullable>
4-
<AvaloniaVersion>11.1.3</AvaloniaVersion>
4+
<AvaloniaVersion>11.1.0</AvaloniaVersion>
55
</PropertyGroup>
66
</Project>

Pixed.Android/AndroidStream.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Pixed.Application.IO;
2+
using System;
3+
using System.IO;
4+
5+
namespace Pixed.Android;
6+
internal class AndroidStreamWrite(Stream stream) : StreamBase(stream)
7+
{
8+
private readonly MemoryStream _internalStream = new();
9+
public override bool CanRead => _internalStream.CanRead;
10+
11+
public override bool CanSeek => _internalStream.CanSeek;
12+
13+
public override bool CanWrite => _internalStream.CanWrite;
14+
15+
public override long Length => _internalStream.Length;
16+
17+
public override long Position { get => _internalStream.Position; set => _internalStream.Position = value; }
18+
19+
public override void Flush()
20+
{
21+
_internalStream.Flush();
22+
_stream.Flush();
23+
}
24+
25+
public override int Read(byte[] buffer, int offset, int count)
26+
{
27+
return _internalStream.Read(buffer, offset, count);
28+
}
29+
30+
public override long Seek(long offset, SeekOrigin origin)
31+
{
32+
return _internalStream.Seek(offset, origin);
33+
}
34+
35+
public override void SetLength(long value)
36+
{
37+
_internalStream.SetLength(value);
38+
}
39+
40+
public override void Write(byte[] buffer, int offset, int count)
41+
{
42+
_internalStream.Write(buffer, offset, count);
43+
}
44+
45+
protected override void Dispose(bool disposing)
46+
{
47+
var buffer = _internalStream.ToArray();
48+
_stream.Write(buffer, 0, buffer.Length);
49+
_internalStream.Dispose();
50+
}
51+
}
52+
53+
internal class AndroidStreamRead(Stream stream) : StreamBase(stream)
54+
{
55+
public override bool CanRead => _stream.CanRead;
56+
57+
public override bool CanSeek => _stream.CanSeek;
58+
59+
public override bool CanWrite => _stream.CanWrite;
60+
61+
public override long Length => _stream.Length;
62+
63+
public override long Position { get => _stream.Position; set => _stream.Position = value; }
64+
65+
public override void Flush()
66+
{
67+
_stream.Flush();
68+
}
69+
70+
public override int Read(byte[] buffer, int offset, int count)
71+
{
72+
return _stream.Read(buffer, offset, count);
73+
}
74+
75+
public override long Seek(long offset, SeekOrigin origin)
76+
{
77+
return _stream.Seek(offset, origin);
78+
}
79+
80+
public override void SetLength(long value)
81+
{
82+
_stream.SetLength(value);
83+
}
84+
85+
public override void Write(byte[] buffer, int offset, int count)
86+
{
87+
throw new NotImplementedException();
88+
}
89+
90+
protected override void Dispose(bool disposing)
91+
{
92+
_stream.Dispose();
93+
}
94+
}
95+

Pixed.Android/Icon.png

11 KB
Loading

Pixed.Android/MainActivity.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using Android.App;
2+
using Android.Content.PM;
3+
using Android.OS;
4+
using Avalonia;
5+
using Avalonia.Android;
6+
using Avalonia.ReactiveUI;
7+
using AvaloniaInside.Shell;
8+
using Pixed.Application;
9+
using Pixed.Application.IO;
10+
using Pixed.Application.Platform;
11+
using Pixed.Application.Utils;
12+
using System.Threading.Tasks;
13+
using Xamarin.Essentials;
14+
15+
namespace Pixed.Android;
16+
17+
[Activity(
18+
Label = "Pixed - Pixelart Editor",
19+
Icon = "@mipmap/pixed_icon",
20+
MainLauncher = true,
21+
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
22+
public class MainActivity : AvaloniaMainActivity<App>
23+
{
24+
protected override async void OnCreate(Bundle? savedInstanceState)
25+
{
26+
AndroidX.Core.SplashScreen.SplashScreen.InstallSplashScreen(this);
27+
PlatformSettings.MainActivity = this;
28+
PlatformFolder.Context = this;
29+
StreamBase.StreamReadImpl = typeof(AndroidStreamRead);
30+
StreamBase.StreamWriteImpl = typeof(AndroidStreamWrite);
31+
base.OnCreate(savedInstanceState);
32+
Platform.Init(this, savedInstanceState);
33+
var permissions = await CheckPermissions();
34+
35+
if (permissions != PermissionStatus.Granted)
36+
{
37+
FinishAffinity();
38+
}
39+
}
40+
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
41+
{
42+
return base.CustomizeAppBuilder(builder)
43+
.LogToTrace()
44+
.UseReactiveUI()
45+
.UseShell()
46+
.SetPlatformFolder(new PlatformFolder())
47+
.SetSettings(new PlatformSettings());
48+
}
49+
50+
private async Task<PermissionStatus> CheckPermissions()
51+
{
52+
var storageRead = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
53+
var storageWrite = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
54+
55+
if (storageRead == PermissionStatus.Granted && storageWrite == PermissionStatus.Granted)
56+
{
57+
return PermissionStatus.Granted;
58+
}
59+
60+
storageRead = await Permissions.RequestAsync<Permissions.StorageRead>();
61+
storageWrite = await Permissions.RequestAsync<Permissions.StorageWrite>();
62+
63+
if (storageRead != PermissionStatus.Granted || storageWrite != PermissionStatus.Granted)
64+
{
65+
return PermissionStatus.Denied;
66+
}
67+
68+
return PermissionStatus.Granted;
69+
}
70+
}
71+

Pixed.Android/Pixed.Android.csproj

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net8.0-android34.0</TargetFramework>
5+
<SupportedOSPlatformVersion>26.0</SupportedOSPlatformVersion>
6+
<Nullable>enable</Nullable>
7+
<ApplicationId>com.CompanyName.AvaloniaTest</ApplicationId>
8+
<ApplicationVersion>1</ApplicationVersion>
9+
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
10+
<AndroidPackageFormat>apk</AndroidPackageFormat>
11+
<AndroidEnableProfiledAot>False</AndroidEnableProfiledAot>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<AndroidResource Include="Icon.png">
16+
<Link>Resources\drawable\Icon.png</Link>
17+
</AndroidResource>
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<PackageReference Include="Avalonia.Android" Version="11.2.2" />
22+
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.13" />
23+
<PackageReference Include="Xamarin.Essentials" Version="1.8.1" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="..\Pixed.Application\Pixed.Application.csproj" />
28+
</ItemGroup>
29+
</Project>

Pixed.Android/PlatformFolder.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Android.Content;
2+
using Avalonia.Platform.Storage;
3+
using Pixed.Application.IO;
4+
using Pixed.Application.Platform;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Threading.Tasks;
8+
9+
namespace Pixed.Android;
10+
internal class PlatformFolder : IPlatformFolder
11+
{
12+
public static Context Context { get; set; }
13+
14+
public IStorageContainerFile Convert(IStorageFile value)
15+
{
16+
return new PlatformStorageContainerFile(value);
17+
}
18+
19+
public async IAsyncEnumerable<IStorageContainerFile> GetFiles(FolderType folder)
20+
{
21+
string[] dirs = Directory.GetFiles(GetFolderPath(folder));
22+
23+
foreach (string dir in dirs)
24+
{
25+
yield return new PlatformStorageContainerFile(dir);
26+
}
27+
}
28+
29+
public Task<IStorageContainerFile> GetFile(string filename, FolderType folderType)
30+
{
31+
return Task.FromResult((IStorageContainerFile)new PlatformStorageContainerFile(Path.Combine(GetFolderPath(folderType), filename)));
32+
}
33+
34+
public void Initialize(IStorageProvider storageProvider)
35+
{
36+
//Unused
37+
}
38+
39+
private static string GetFolderPath(FolderType type)
40+
{
41+
return type switch
42+
{
43+
FolderType.Root => GetPixedFolder(),
44+
FolderType.Palettes => GetPalettesFolder(),
45+
_ => string.Empty,
46+
};
47+
}
48+
private static string GetPalettesFolder()
49+
{
50+
return GetFolderAbsolute("Palettes");
51+
}
52+
53+
private static string GetPixedFolder()
54+
{
55+
return GetFolderAbsolute("Pixed");
56+
}
57+
58+
private static string GetFolderAbsolute(string folderName)
59+
{
60+
return Context.GetDir(folderName, FileCreationMode.Private).AbsolutePath;
61+
}
62+
}

Pixed.Android/PlatformSettings.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Android.App;
2+
using Avalonia.Controls.ApplicationLifetimes;
3+
using Pixed.Application.Platform;
4+
namespace Pixed.Android;
5+
internal class PlatformSettings : IPlatformSettings
6+
{
7+
public static Activity MainActivity { get; internal set; }
8+
public IApplicationLifetime ApplicationLifetime { get; set; }
9+
public bool ExtensionsEnabled => false;
10+
public bool RecentFilesEnabled => false;
11+
public bool ExtensionsOnSave => true;
12+
13+
public void Close()
14+
{
15+
MainActivity?.FinishAffinity();
16+
}
17+
18+
public string GetVersion()
19+
{
20+
return Xamarin.Essentials.VersionTracking.CurrentVersion;
21+
}
22+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Avalonia.Platform.Storage;
2+
using Pixed.Application.IO;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
6+
namespace Pixed.Android;
7+
internal class PlatformStorageContainerFile(string file) : IStorageContainerFile
8+
{
9+
private readonly FileInfo _info = new(file);
10+
11+
public string Name => _info.Name;
12+
13+
public string Path => _info.FullName;
14+
public string Extension => _info.Extension;
15+
16+
public PlatformStorageContainerFile(IStorageFile file) : this(file.Path.AbsolutePath)
17+
{
18+
}
19+
20+
public Task<StreamBase> OpenRead()
21+
{
22+
return Task.FromResult(StreamBase.CreateRead(_info.OpenRead()));
23+
}
24+
25+
public Task<StreamBase> OpenWrite()
26+
{
27+
return Task.FromResult(StreamBase.CreateWrite(_info.OpenWrite()));
28+
}
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="com.nejman.pixed" android:versionCode="17" android:versionName="1.7">
3+
<uses-permission android:name="android.permission.INTERNET" />
4+
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
5+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
6+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7+
<application android:label="Pixed" android:icon="@mipmap/pixed_icon" android:theme="@style/Theme.Splash" />
8+
</manifest>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<item>
5+
<color android:color="@color/splash_background"/>
6+
</item>
7+
8+
<item android:drawable="@drawable/icon"
9+
android:width="120dp"
10+
android:height="120dp"
11+
android:gravity="center" />
12+
13+
</layer-list>

0 commit comments

Comments
 (0)