Add NuGet package assets and fix license
- 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>
This commit is contained in:
@@ -13,7 +13,10 @@
|
||||
<Description>Popups for MAUI with multi-window support. Fork of Mopups by LuckyDucko.</Description>
|
||||
<PackageProjectUrl>https://git.marketally.com/marketally/MarketAlly.Mopups</PackageProjectUrl>
|
||||
<RepositoryUrl>https://git.marketally.com/marketally/MarketAlly.Mopups</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageLicenseExpression>BSD-3-Clause</PackageLicenseExpression>
|
||||
<Copyright>Copyright (c) 2022, Tyson Elliot Hooker. All rights reserved.</Copyright>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
|
||||
@@ -104,4 +107,9 @@
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.82" />
|
||||
<PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.82" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="icon.png" Pack="true" PackagePath="\" />
|
||||
<None Include="..\..\..\..\README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
BIN
Mopups/Mopups.Maui/icon.png
Normal file
BIN
Mopups/Mopups.Maui/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
365
README.md
365
README.md
@@ -1,175 +1,290 @@
|
||||
# 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)
|
||||
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<h1 align="center">Mopups</h3>
|
||||
<p align="center">
|
||||
Customisable Popups for MAUI
|
||||
<br />
|
||||
</p>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<!-- TABLE OF CONTENTS -->
|
||||
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
|
||||
|
||||
[](https://www.nuget.org/packages/Mopups/)
|
||||
[](https://www.nuget.org/packages/Mopups/)
|
||||
* [About the Project](#about-the-project)
|
||||
* [Getting Started](#getting-started)
|
||||
* [Installation](#installation)
|
||||
* [Usage](#usage)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
- [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)
|
||||
|
||||
<!-- ABOUT THE PROJECT -->
|
||||
## About The Project
|
||||
- **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)
|
||||
|
||||
Mopups is a replacement for the "Rg.Plugins.Popups" plugin for Xamarin. Mopups intends to provide a similar experience to this plugin, however also clean up the code base and provide forward looking enhancements. Developers familar with the original plugin should find it a smooth transition, but we do recommend reading the wiki and reaching out with any issues.
|
||||
### New in MarketAlly.Mopups v2.0.0
|
||||
|
||||
The "PreBaked" is a neat blend of Mopups and AsyncAwaitBestPractices plugins to bring you a quick way to add popups into your MAUIs App using familiar concepts
|
||||
- **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`
|
||||
|
||||
Platforms Supported (Current)
|
||||
- Android
|
||||
- iOS
|
||||
- Windows
|
||||
- MacOS (Mac Catalyst) (This is a bit iffy..)
|
||||
## Installation
|
||||
|
||||
Install via NuGet Package Manager:
|
||||
|
||||
Below is a video by @jfversluis introducing Mopups
|
||||
[](https://youtu.be/OGWhgASmSto)
|
||||
|
||||
|
||||
<!-- GETTING STARTED -->
|
||||
## Getting Started
|
||||
|
||||
First, you must follow the [initialisation](https://github.com/LuckyDucko/Mopups/wiki/Setup)
|
||||
|
||||
### Installation
|
||||
|
||||
You can install the nuget by looking up 'Mopups' in your nuget package manager, or by getting it [here](https://www.nuget.org/packages/Mopups/)
|
||||
|
||||
|
||||
|
||||
<!-- USAGE EXAMPLES -->
|
||||
## Usage
|
||||
here is an example of what this plugin makes easy (Looks slow due to giphy)
|
||||
|
||||

|
||||
|
||||
|
||||
### New Example
|
||||
To Use the plugin for its inbuilt popup pages in a basic setting (Dual/Single Response, Login, TextInput EntryInput,and loader.) All you need are these one liners
|
||||
|
||||
`SingleResponse Popup Page`
|
||||
```csharp
|
||||
return await SingleResponseViewModel.AutoGenerateBasicPopup(Color.HotPink, Color.Black, "I Accept", Color.Gray, "Good Job, enjoy this single response example", "thumbsup.png");
|
||||
```bash
|
||||
dotnet add package MarketAlly.Mopups
|
||||
```
|
||||
|
||||
`DualResponse Popup Page`
|
||||
```csharp
|
||||
return await DualResponseViewModel.AutoGenerateBasicPopup(Color.WhiteSmoke, Color.Red, "Okay", Color.WhiteSmoke, Color.Green, "Looks Good!", Color.DimGray, "This is an example of a dual response popup page", "thumbsup.png");
|
||||
Or via Package Manager Console:
|
||||
|
||||
```powershell
|
||||
Install-Package MarketAlly.Mopups
|
||||
```
|
||||
|
||||
`Loader Popup Page`
|
||||
```csharp
|
||||
await PreBakedMopupService.GetInstance().WrapTaskInLoader(Task.Delay(10000), Color.Blue, Color.White, LoadingReasons(), Color.Black);
|
||||
```
|
||||
## Quick Start
|
||||
|
||||
`Text Input PopupPage`
|
||||
```csharp
|
||||
await TextInputViewModel.AutoGenerateBasicPopup(Color.WhiteSmoke, Color.Red, "Cancel", Color.WhiteSmoke, Color.Green, "Submit", Color.DimGray, "Text input Example", string.Empty);
|
||||
```
|
||||
`Entry Input PopupPage`
|
||||
```csharp
|
||||
await EntryInputViewModel.AutoGenerateBasicPopup(Color.WhiteSmoke, Color.Red, "Cancel", Color.WhiteSmoke, Color.Green, "Submit", Color.DimGray, "Text input Example", string.Empty);
|
||||
```
|
||||
### 1. Configure in MauiProgram.cs
|
||||
|
||||
`LoginPage PopupPage`
|
||||
```csharp
|
||||
var (username, password) = await LoginViewModel.AutoGenerateBasicPopup(Color.WhiteSmoke, Color.Red, "Cancel", Color.WhiteSmoke, Color.Green, "Submit", Color.DimGray, string.Empty, "Username Here", string.Empty, "Password here", "thumbsup.png", 0, 0);
|
||||
```
|
||||
using Mopups.Hosting;
|
||||
|
||||
or, to return from the loader a value
|
||||
```csharp
|
||||
await PreBakedMopupService.GetInstance().WrapReturnableTaskInLoader<bool, LoaderPopupPage>(IndepthCheckAgainstDatabase(), Color.Blue, Color.White, LoadingReasons(), Color.Black);
|
||||
```
|
||||
|
||||
you can also add in synchronous functions, however they are wrapped in a task
|
||||
```csharp
|
||||
|
||||
private bool LongRunningFunction(int millisecondDelay)
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
Thread.Sleep(millisecondDelay);
|
||||
return true;
|
||||
}
|
||||
await PreBakedMopupService.GetInstance().WrapReturnableFuncInLoader(LongRunningFunction, 6000, Color.Blue, Color.White, LoadingReasons(), Color.Black);
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.ConfigureMopups(); // Add this line
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
```
|
||||
|
||||
## That's it! for advanced usage read on
|
||||
### 2. Create a Popup Page
|
||||
|
||||
In Version 1.2.0, Mopups has added some pre created pages that can provide users the ability to return data from popups. I have also added the ability to overload the look of these pages and create your own.
|
||||
```csharp
|
||||
using Mopups.Pages;
|
||||
|
||||
I do wish it were simpler, however, with the limited time i have to work on this, it'll have to do.
|
||||
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()) }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This set of API's will be used for when the basic API wont cut it, without relying on me making another overload for every situation under the sun.
|
||||
### 3. Show the Popup
|
||||
|
||||
This API introduces
|
||||
```csharp
|
||||
using Mopups.Services;
|
||||
|
||||
`GeneratePopup<TPopupPage>`
|
||||
Which allows you to supply your own popuppage xaml which will then be attached to whatever VM you called it from.
|
||||
// Show on main window (default behavior)
|
||||
await MopupService.Instance.PushAsync(new MyPopupPage());
|
||||
|
||||
`GeneratePopup(Dictionary<string, object> propertyDictionary)`
|
||||
Which allows you have a dictionary of values that a popup uses, pass and automatically attach to the appropriate properties on the VM side
|
||||
// Show on specific window (NEW in v2.0.0)
|
||||
await MopupService.Instance.PushAsync(new MyPopupPage(), targetWindow);
|
||||
```
|
||||
|
||||
These are both non-static. and require you to have an instance of the ViewModel to work with. Hence
|
||||
## Multi-Window Support
|
||||
|
||||
`<ViewModelClassNameHere>.GenerateVM()`
|
||||
Which provides you with a new instance of that VM
|
||||
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:
|
||||
|
||||
`<ViewModelClassNameHere>.PullViewModelProperties()`
|
||||
Which collects all the properties of a VM, and provides them to you in a dictionary, so you can reuse and also while debugging, check what exists/whats been changed
|
||||
Returns this `Dictionary<string, (object property, Type propertyType)> `
|
||||
- Helper/tool windows
|
||||
- Document windows
|
||||
- Settings panels
|
||||
- Floating utility windows
|
||||
|
||||
However, for initialisation, i internally (and you can use) the following function
|
||||
`<ViewModelClassNameHere>.InitialiseOptionalProperties(Dictionary<string, object> optionalProperties)`
|
||||
Which will attempt to set each of the viewmodel properties with the corrosponding value in the dictionary
|
||||
### API
|
||||
|
||||
So, to fix that, i provide
|
||||
`<ViewModelClassNameHere>.FinalisePreparedProperties(Dictionary<string, (object property, Type propertyType)> viewModelProperties)`
|
||||
Which takes in the `Dictionary<string, (object property, Type propertyType)> ` and creates `Dictionary<string, object> optionalProperties`
|
||||
```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
|
||||
|
||||
**If you want to make your own Popup Page**
|
||||
```csharp
|
||||
public class HelperWindow : Window
|
||||
{
|
||||
public async Task ShowConfirmation()
|
||||
{
|
||||
var popup = new ConfirmationPopup();
|
||||
|
||||
This is the real power of this Plugin . If you look at the source for DualResponsePopupPage, or the SingleResponse version you'll notice that they are just simple Xaml Pages. Nothing fancy.
|
||||
// Pass 'this' to show popup on this window, not the main window
|
||||
await MopupService.Instance.PushAsync(popup, this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can create the full thing yourself
|
||||
1. Create Xaml Page with codebehind
|
||||
2. Create your ViewModel that is associated with the popup, lets call ours `InformationPopupPage`
|
||||
3. Ensure your ViewModel inherits from `PopupViewModel<TReturnable>` where `TReturnable` is what you want the popuppage to return to its caller
|
||||
4. Ensure that your xaml page codebehind inherits from `PopupPage` (requirement to use rg plugins popup) and `IGenericViewModel<TViewModel>` where `TViewModel` is your Viewmodel, in our case it will be `IGenericViewModel<InformationPopupPage>`
|
||||
5. You're ready to start using it the same as `DualResponsePopupPage`
|
||||
### Platform Implementation Details
|
||||
|
||||
or you can provide your own Xaml Page, with a codebehind that inherits from `PopupPage` and `IGenericViewModel<TViewModel>` where `TViewModel` is the plugin provided VM you wish to use.
|
||||
| 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` |
|
||||
|
||||
to use this version, just call `TViewModel.GeneratePopup<YourXamlPopupPage>()`
|
||||
## 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 -->
|
||||
## License
|
||||
This project uses the MIT License
|
||||
|
||||
<!-- CONTACT -->
|
||||
## Contact
|
||||
My [Github](https://github.com/LuckyDucko),
|
||||
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.*
|
||||
|
||||
Reference in New Issue
Block a user