- Add icon.png for NuGet package - Add PackageIcon and PackageReadmeFile to csproj - Fix license from MIT to BSD-3-Clause (correct license per original) - Add Copyright notice crediting original author 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
291 lines
8.5 KiB
Markdown
291 lines
8.5 KiB
Markdown
# MarketAlly.Mopups
|
|
|
|
[](https://www.nuget.org/packages/MarketAlly.Mopups/)
|
|
[](https://www.nuget.org/packages/MarketAlly.Mopups/)
|
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
[](https://dotnet.microsoft.com/download)
|
|
[](https://dotnet.microsoft.com/apps/maui)
|
|
|
|
Customizable popups for .NET MAUI with multi-window support. A fork of [Mopups](https://github.com/LuckyDucko/Mopups) by Tyson Hooker (LuckyDucko) with enhanced multi-window capabilities for all platforms.
|
|
|
|
## Table of Contents
|
|
|
|
- [Features](#features)
|
|
- [Installation](#installation)
|
|
- [Quick Start](#quick-start)
|
|
- [Multi-Window Support](#multi-window-support)
|
|
- [Usage](#usage)
|
|
- [Platform Support](#platform-support)
|
|
- [Requirements](#requirements)
|
|
- [License](#license)
|
|
- [Acknowledgments](#acknowledgments)
|
|
|
|
## Features
|
|
|
|
### Core Capabilities (from Mopups)
|
|
|
|
- **Customizable Popups**: Full control over popup appearance and behavior
|
|
- **Async/Await Pattern**: Modern asynchronous popup handling
|
|
- **Animation Support**: Built-in appearing and disappearing animations
|
|
- **System Padding**: Automatic safe area handling
|
|
- **Back Button Handling**: Customizable back button behavior
|
|
- **Cross-Platform**: iOS, Android, Windows, and macOS (Mac Catalyst)
|
|
|
|
### New in MarketAlly.Mopups v2.0.0
|
|
|
|
- **Multi-Window Support**: Display popups on specific windows instead of always on the main window
|
|
- Windows: Uses target window's `XamlRoot`
|
|
- iOS/iPadOS: Uses target window's `UIWindowScene`
|
|
- macOS Catalyst: Uses target window's `UIWindowScene`
|
|
- Android: Uses target window's Activity `DecorView`
|
|
|
|
## Installation
|
|
|
|
Install via NuGet Package Manager:
|
|
|
|
```bash
|
|
dotnet add package MarketAlly.Mopups
|
|
```
|
|
|
|
Or via Package Manager Console:
|
|
|
|
```powershell
|
|
Install-Package MarketAlly.Mopups
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### 1. Configure in MauiProgram.cs
|
|
|
|
```csharp
|
|
using Mopups.Hosting;
|
|
|
|
public static MauiApp CreateMauiApp()
|
|
{
|
|
var builder = MauiApp.CreateBuilder();
|
|
builder
|
|
.UseMauiApp<App>()
|
|
.ConfigureMopups(); // Add this line
|
|
|
|
return builder.Build();
|
|
}
|
|
```
|
|
|
|
### 2. Create a Popup Page
|
|
|
|
```csharp
|
|
using Mopups.Pages;
|
|
|
|
public class MyPopupPage : PopupPage
|
|
{
|
|
public MyPopupPage()
|
|
{
|
|
Content = new StackLayout
|
|
{
|
|
Children =
|
|
{
|
|
new Label { Text = "Hello from popup!" },
|
|
new Button { Text = "Close", Command = new Command(async () =>
|
|
await MopupService.Instance.PopAsync()) }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Show the Popup
|
|
|
|
```csharp
|
|
using Mopups.Services;
|
|
|
|
// Show on main window (default behavior)
|
|
await MopupService.Instance.PushAsync(new MyPopupPage());
|
|
|
|
// Show on specific window (NEW in v2.0.0)
|
|
await MopupService.Instance.PushAsync(new MyPopupPage(), targetWindow);
|
|
```
|
|
|
|
## Multi-Window Support
|
|
|
|
The key enhancement in MarketAlly.Mopups is the ability to display popups on specific windows. This is essential for applications with multiple windows, such as:
|
|
|
|
- Helper/tool windows
|
|
- Document windows
|
|
- Settings panels
|
|
- Floating utility windows
|
|
|
|
### API
|
|
|
|
```csharp
|
|
// Standard push (uses main window)
|
|
Task PushAsync(PopupPage page, bool animate = true);
|
|
|
|
// Window-aware push (NEW)
|
|
Task PushAsync(PopupPage page, Window? window, bool animate = true);
|
|
```
|
|
|
|
### Example: Showing Dialog on Helper Window
|
|
|
|
```csharp
|
|
public class HelperWindow : Window
|
|
{
|
|
public async Task ShowConfirmation()
|
|
{
|
|
var popup = new ConfirmationPopup();
|
|
|
|
// Pass 'this' to show popup on this window, not the main window
|
|
await MopupService.Instance.PushAsync(popup, this);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Platform Implementation Details
|
|
|
|
| Platform | How Window is Used |
|
|
|----------|-------------------|
|
|
| Windows | Gets `XamlRoot` from the target window's native `Microsoft.UI.Xaml.Window` |
|
|
| iOS/iPadOS | Gets `UIWindowScene` from the target window's native `UIWindow` |
|
|
| macOS Catalyst | Gets `UIWindowScene` from the target window's native `UIWindow` |
|
|
| Android | Gets `DecorView` from the target window's `Activity` |
|
|
|
|
## Usage
|
|
|
|
### Basic Popup Operations
|
|
|
|
```csharp
|
|
// Push a popup
|
|
await MopupService.Instance.PushAsync(new MyPopupPage());
|
|
|
|
// Push with animation control
|
|
await MopupService.Instance.PushAsync(new MyPopupPage(), animate: false);
|
|
|
|
// Pop the topmost popup
|
|
await MopupService.Instance.PopAsync();
|
|
|
|
// Pop all popups
|
|
await MopupService.Instance.PopAllAsync();
|
|
|
|
// Remove specific popup
|
|
await MopupService.Instance.RemovePageAsync(specificPopup);
|
|
|
|
// Check popup stack
|
|
var popupStack = MopupService.Instance.PopupStack;
|
|
```
|
|
|
|
### Events
|
|
|
|
```csharp
|
|
MopupService.Instance.Pushing += (sender, args) =>
|
|
Console.WriteLine($"Pushing: {args.Page}");
|
|
|
|
MopupService.Instance.Pushed += (sender, args) =>
|
|
Console.WriteLine($"Pushed: {args.Page}");
|
|
|
|
MopupService.Instance.Popping += (sender, args) =>
|
|
Console.WriteLine($"Popping: {args.Page}");
|
|
|
|
MopupService.Instance.Popped += (sender, args) =>
|
|
Console.WriteLine($"Popped: {args.Page}");
|
|
```
|
|
|
|
### PopupPage Properties
|
|
|
|
```csharp
|
|
public class MyPopupPage : PopupPage
|
|
{
|
|
public MyPopupPage()
|
|
{
|
|
// Background click dismisses popup
|
|
CloseWhenBackgroundIsClicked = true;
|
|
|
|
// Handle safe areas
|
|
HasSystemPadding = true;
|
|
|
|
// Background color
|
|
BackgroundColor = Color.FromRgba("#80000000");
|
|
}
|
|
|
|
// Override for custom back button behavior
|
|
protected override bool OnBackButtonPressed()
|
|
{
|
|
// Return true to prevent dismissal
|
|
return false;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Platform Support
|
|
|
|
| Platform | Minimum Version | Multi-Window Support |
|
|
|----------|-----------------|---------------------|
|
|
| iOS | 11.0 | Yes (iOS 13+ with UIScene) |
|
|
| Android | API 21 (5.0) | Yes (Android 7.0+ multi-window) |
|
|
| Windows | 10.0.17763.0 | Yes |
|
|
| macOS | 13.1 (Catalyst) | Yes |
|
|
|
|
## Requirements
|
|
|
|
- .NET 9.0
|
|
- Microsoft.Maui.Controls 9.0+
|
|
- Microsoft.Maui.Essentials 9.0+
|
|
|
|
## License
|
|
|
|
This project is licensed under the **BSD 3-Clause License**.
|
|
|
|
```
|
|
BSD 3-Clause License
|
|
|
|
Copyright (c) 2022, Tyson Elliot Hooker
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
3. Neither the name of the copyright holder nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
```
|
|
|
|
## Acknowledgments
|
|
|
|
This project is a fork of [Mopups](https://github.com/LuckyDucko/Mopups), originally created by **Tyson Hooker (LuckyDucko)**. We extend our gratitude to:
|
|
|
|
- **Tyson Hooker** - Original author and maintainer of Mopups
|
|
- **Maksym Koshovyi** - Contributor
|
|
- **Aswin P G** - Contributor
|
|
- **Kirill Lyubimov** - Contributor
|
|
- **Martijn Van Dijk** - Contributor
|
|
- **Shane Neuville** - Contributor
|
|
|
|
Mopups itself was created as a replacement for the "Rg.Plugins.Popups" plugin for Xamarin, providing a modern popup solution for .NET MAUI.
|
|
|
|
### Additional Resources
|
|
|
|
- [Original Mopups Repository](https://github.com/LuckyDucko/Mopups)
|
|
- [Mopups Introduction Video by Gerald Versluis](https://youtu.be/OGWhgASmSto)
|
|
|
|
---
|
|
|
|
**Built with precision by [MarketAlly](https://marketally.com)**
|
|
|
|
*Multi-window popup support for .NET MAUI applications.*
|