diff --git a/Directory.Packages.props b/Directory.Packages.props index b5802d1..0521c14 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,7 @@ + diff --git a/LanMountainDesktop.Mobile.Android/LanMountainDesktop.Mobile.Android.csproj b/LanMountainDesktop.Mobile.Android/LanMountainDesktop.Mobile.Android.csproj new file mode 100644 index 0000000..0d711c0 --- /dev/null +++ b/LanMountainDesktop.Mobile.Android/LanMountainDesktop.Mobile.Android.csproj @@ -0,0 +1,23 @@ + + + net10.0-android + 24 + Exe + enable + enable + org.lanmountain.desktop + 1 + 0.0.0-dev + apk + true + + + + + + + + + + + diff --git a/LanMountainDesktop.Mobile.Android/MainActivity.cs b/LanMountainDesktop.Mobile.Android/MainActivity.cs new file mode 100644 index 0000000..7167066 --- /dev/null +++ b/LanMountainDesktop.Mobile.Android/MainActivity.cs @@ -0,0 +1,19 @@ +using Android.App; +using Android.Content.PM; +using Avalonia.Android; + +namespace LanMountainDesktop.Mobile.Android; + +/// +/// Android 入口 Activity。承载 MobileApp(单视图组件面板)。 +/// Avalonia 12 起 AppBuilder 定制移至 。 +/// +[Activity( + Label = "阑山桌面", + Theme = "@style/MyTheme.NoActionBar", + Icon = "@drawable/icon", + MainLauncher = true, + ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] +public class MainActivity : AvaloniaMainActivity +{ +} diff --git a/LanMountainDesktop.Mobile.Android/MobileAndroidApplication.cs b/LanMountainDesktop.Mobile.Android/MobileAndroidApplication.cs new file mode 100644 index 0000000..32677ce --- /dev/null +++ b/LanMountainDesktop.Mobile.Android/MobileAndroidApplication.cs @@ -0,0 +1,26 @@ +using Android.App; +using Android.Runtime; +using Avalonia; +using Avalonia.Android; +using LanMountainDesktop.Mobile; + +namespace LanMountainDesktop.Mobile.Android; + +/// +/// Android 应用级入口。Avalonia 12 中 AppBuilder 的创建/定制由 +/// AvaloniaAndroidApplication<TApp> 子类负责(而非 Activity)。 +/// +[Application] +public class MobileAndroidApplication : AvaloniaAndroidApplication +{ + protected MobileAndroidApplication(nint javaReference, JniHandleOwnership transfer) + : base(javaReference, transfer) + { + } + + protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) + { + return base.CustomizeAppBuilder(builder) + .WithInterFont(); + } +} diff --git a/LanMountainDesktop.Mobile.Android/Resources/drawable/icon.png b/LanMountainDesktop.Mobile.Android/Resources/drawable/icon.png new file mode 100644 index 0000000..c89feab Binary files /dev/null and b/LanMountainDesktop.Mobile.Android/Resources/drawable/icon.png differ diff --git a/LanMountainDesktop.Mobile.Android/Resources/values/styles.xml b/LanMountainDesktop.Mobile.Android/Resources/values/styles.xml new file mode 100644 index 0000000..668bb66 --- /dev/null +++ b/LanMountainDesktop.Mobile.Android/Resources/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/LanMountainDesktop.Mobile/LanMountainDesktop.Mobile.csproj b/LanMountainDesktop.Mobile/LanMountainDesktop.Mobile.csproj new file mode 100644 index 0000000..6daa19d --- /dev/null +++ b/LanMountainDesktop.Mobile/LanMountainDesktop.Mobile.csproj @@ -0,0 +1,23 @@ + + + net10.0 + enable + enable + true + + + + + + + + + + + + + + + + + diff --git a/LanMountainDesktop.Mobile/MobileApp.axaml b/LanMountainDesktop.Mobile/MobileApp.axaml new file mode 100644 index 0000000..481d86a --- /dev/null +++ b/LanMountainDesktop.Mobile/MobileApp.axaml @@ -0,0 +1,8 @@ + + + + + diff --git a/LanMountainDesktop.Mobile/MobileApp.axaml.cs b/LanMountainDesktop.Mobile/MobileApp.axaml.cs new file mode 100644 index 0000000..ca5d6bb --- /dev/null +++ b/LanMountainDesktop.Mobile/MobileApp.axaml.cs @@ -0,0 +1,33 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using LanMountainDesktop.Mobile.ViewModels; +using LanMountainDesktop.Mobile.Views; + +namespace LanMountainDesktop.Mobile; + +/// +/// 移动端应用入口。以单视图生命周期承载组件面板。 +/// 与桌面宿主 (LanMountainDesktop.App) 共享契约、外观与组件运行时, +/// 但不包含桌面层、托盘、进程外插件等桌面专属能力。 +/// +public partial class MobileApp : Application +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is ISingleViewApplicationLifetime singleView) + { + singleView.MainView = new WidgetPanelView + { + DataContext = new WidgetPanelViewModel() + }; + } + + base.OnFrameworkInitializationCompleted(); + } +} diff --git a/LanMountainDesktop.Mobile/ViewModels/WidgetPanelViewModel.cs b/LanMountainDesktop.Mobile/ViewModels/WidgetPanelViewModel.cs new file mode 100644 index 0000000..5bc99c0 --- /dev/null +++ b/LanMountainDesktop.Mobile/ViewModels/WidgetPanelViewModel.cs @@ -0,0 +1,57 @@ +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace LanMountainDesktop.Mobile.ViewModels; + +/// +/// 组件面板视图模型。 +/// 移动端不提供桌面自由摆放,组件以卡片流形式呈现。 +/// 后续由组件运行时(DesktopComponents.Runtime)通过 +/// 注入真实组件视图。 +/// +public sealed partial class WidgetPanelViewModel : ObservableObject +{ + public ObservableCollection Widgets { get; } = []; + + [ObservableProperty] + private string _title = "组件面板"; + + public WidgetPanelViewModel() + { + // 首版占位卡片:标记组件运行时的接入点。 + Widgets.Add(new WidgetCardViewModel("时间表", "课程表 / 日程组件将在此呈现")); + Widgets.Add(new WidgetCardViewModel("天气", "天气组件将在此呈现")); + Widgets.Add(new WidgetCardViewModel("插件组件", "已安装插件提供的组件将在此呈现")); + } + + /// + /// 组件运行时接入点:注册一个真实组件卡片。 + /// + public void RegisterWidget(WidgetCardViewModel widget) + { + Widgets.Add(widget); + } +} + +/// +/// 单个组件卡片。 为空时显示占位说明文本, +/// 非空时承载组件运行时提供的真实控件。 +/// +public sealed partial class WidgetCardViewModel : ObservableObject +{ + [ObservableProperty] + private string _name; + + [ObservableProperty] + private string _placeholder; + + [ObservableProperty] + private object? _content; + + public WidgetCardViewModel(string name, string placeholder, object? content = null) + { + _name = name; + _placeholder = placeholder; + _content = content; + } +} diff --git a/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml b/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml new file mode 100644 index 0000000..47172e0 --- /dev/null +++ b/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml.cs b/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml.cs new file mode 100644 index 0000000..5e909a2 --- /dev/null +++ b/LanMountainDesktop.Mobile/Views/WidgetPanelView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace LanMountainDesktop.Mobile.Views; + +public partial class WidgetPanelView : UserControl +{ + public WidgetPanelView() + { + InitializeComponent(); + } +}