Easiest Way to Show Alert Dialog in Flutter App

Emerge Alert Dialog

An emerge alert dialog package is allows developers to easily create and display alert dialogs with custom animations. Emerge dialogs are used to display important information or messages to the user and often include a call to action, such as a button to confirm or dismiss the dialog.

In the context of the Emerge framework, an Alert Dialog is a type of dialog box that can be used to display an alert message or to prompt the user for a response within the context of an Emerge application.

Usage

Example

To use this package :

  • add the dependency to your pubspec.yaml file.
dependencies:

  emerge_alert_dialog: ^0.0.3

How to use

    Future<void> _showMyDialog(BuildContext context) async {
        return showDialog<void>(
        context: context,
        barrierDismissible: true,
        builder: (BuildContext context) {
            return EmergeAlertDialog(
            alignment: Alignment.bottomCenter,
            emergeAlertDialogOptions: EmergeAlertDialogOptions(
                title: const Text("Privacy Info"),
             ),
          );
        },
      );
    }

Screenshot

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add emerge_alert_dialog

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  emerge_alert_dialog: ^0.0.3

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:emerge_alert_dialog/emerge_alert_dialog.dart'; 

example/lib/main.dart

import 'package:emerge_pop_up_example/home_screen.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Emerge Alert Dialog',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const HomeScreen(),
    );
  }
} 

Download Details:

Author: champ96k

Source Code: https://github.com/champ96k/emerge_alert_dialog

#alert #dialog 

Easiest Way to Show Alert Dialog in Flutter App

A Flutter Package to Display Animated Alert Dialogs

cool_alert_two

A Flutter package to display animated alert dialogs.

NOTE: this is a forked version of the original cool_alert plugin which was no longer being actively maintained at the time of writing!

Cool Alert Two includes various bug fixes and improvements that I use in my own projects and which I am aiming to maintain as a public fork. Feel free to contribute!

Usage

To use this package, add cool_alert_two as a dependency in your pubspec.yaml file. And add this import to your file.

import 'package:cool_alert_two/cool_alert_two.dart';

Image

Screenshot  Gif

Example

CoolAlertTwo.show(
   context: context,
   type: CoolAlertType.success,
   text: "Your transaction was successful!",
);

CoolAlertTwo Class

AttributeData typeDescriptionDefault Value
contextBuildContext@requiredNull
typeCoolAlertType@required - Type of alert dialog, ex: CoolAlertType.success for success dialogsNull
titleStringSet a custom title for dialogBased on the CoolAlertType selected
textStringSet the description text of the dialog.Null
widgetWidgetSet any you expect widget of the dialog.Null
confirmBtnTextStringText of confirm button'Ok'
confirmBtnTapFunctionFunction that handle click of confirm button() => Navigator.pop(context)
confirmBtnColorColorColor of confirm ButtonTheme.of(context).primaryColor
cancelBtnTextStringText of cancel button'Cancel'
cancelBtnTapFunctionFunction that handle click of cancel button() => Navigator.pop(context)
barrierDismissibleboolDismiss dialog on touch overlaytrue
animTypeCoolAlertAnimTypeType of dialogue enter animationCoolAlertAnimType.scale
backgroundColorColorBackground color of the animationColor(0xFF515C6F)
confirmBtnTextStyleTextStyleConfirm button text themeTextStyle(color: Colors.white, fontWeight:FontWeight.w600,fontSize: 18.0)
cancelBtnTextStyleTextStyleCancel button text themeTextStyle(color: Colors.grey, fontWeight:FontWeight.w600,fontSize: 18.0)
flareAssetStringCustom flare asset"animation.flr"
flareAnimationNameStringThe name of the flare animation to play"play"
lottieAssetStringCustom lottie asset"animation.json"
autoCloseDurationDurationDetermines how long the dialog stays open for before closingNull
widthdoubleDialog widthMediaQuery.of(context).size.width
loopAnimationbooleanDetermines if the animation should loop or notfalse

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add cool_alert_two

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  cool_alert_two: ^0.1.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:cool_alert_two/cool_alert_two.dart'; 

example/lib/main.dart

import 'package:cool_alert_two/cool_alert_two.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cool Alert',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        fontFamily: GoogleFonts.poppins().fontFamily,
      ),
      home: MyHomePage(title: 'Cool Alert'),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final successAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.success,
          text: 'Transaction completed successfully!',
          autoCloseDuration: Duration(seconds: 2),
        );
      },
      text: 'Success',
      color: Colors.green,
    );

    final errorAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.error,
          title: 'Oops...',
          text: 'Sorry, something went wrong',
          loopAnimation: false,
        );
      },
      text: 'Error',
      color: Colors.red,
    );

    final warningAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.warning,
          text: 'You just broke protocol',
        );
      },
      text: 'Warning',
      color: Colors.orange,
    );

    final infoAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.info,
          text: 'Buy two, get one free',
        );
      },
      text: 'Info',
      color: Colors.blue[100],
    );

    final confirmAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.confirm,
          text: 'Do you want to logout',
          confirmBtnText: 'Yes',
          cancelBtnText: 'No',
          confirmBtnColor: Colors.green,
        );
      },
      text: 'Confirm',
      color: Colors.lightGreen,
    );

    final loadingAlert = _buildButton(
      onTap: () {
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.loading,
        );
      },
      text: 'Loading',
      color: Colors.grey,
    );

    final customAlert = _buildButton(
      onTap: () {
        var _message = '';
        CoolAlertTwo.show(
          context: context,
          type: CoolAlertTwoType.custom,
          barrierDismissible: true,
          confirmBtnText: 'Save',
          widget: TextFormField(
            decoration: InputDecoration(
              hintText: 'Enter Phone Number',
              prefixIcon: Icon(
                Icons.phone_outlined,
              ),
            ),
            textInputAction: TextInputAction.next,
            keyboardType: TextInputType.phone,
            onChanged: (value) => _message = value,
          ),
          onConfirmBtnTap: () async {
            if (_message.length < 5) {
              await CoolAlertTwo.show(
                context: context,
                type: CoolAlertTwoType.error,
                text: 'Please input something',
              );
              return;
            }
            Navigator.pop(context);
            await Future.delayed(Duration(milliseconds: 1000));
            await CoolAlertTwo.show(
              context: context,
              type: CoolAlertTwoType.success,
              text: "Phone number '$_message' has been saved!.",
            );
          },
        );
      },
      text: 'Custom',
      color: Colors.orange,
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            successAlert,
            errorAlert,
            warningAlert,
            infoAlert,
            confirmAlert,
            loadingAlert,
            customAlert,
          ],
        ),
      ),
    );
  }

  Widget _buildButton({VoidCallback? onTap, required String text, Color? color}) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 10.0),
      child: MaterialButton(
        color: color,
        minWidth: double.infinity,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(30.0),
        ),
        onPressed: onTap,
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 15.0),
          child: Text(
            text,
            style: TextStyle(
              color: Colors.white,
            ),
          ),
        ),
      ),
    );
  }
} 

Download Details:

Author: matwright

Source Code: https://github.com/matwright/flutter_cool_alert_two

#flutter #alert 

A Flutter Package to Display Animated Alert Dialogs
Rupert  Beatty

Rupert Beatty

1673923860

FFPopup: Presenting Custom Views As A Popup in iOS

FFPopup

FFPopup is a lightweight library for presenting custom views as a popup.

Features

Support several popup show types

  •  None
  •  Fade In
  •  Grow In
  •  Shrink In
  •  Slide In from top, bottom, left, right
  •  Bounce In from top, bottom, left, right, center
  •  Support custom

Support several popup dismiss types

  •  None
  •  Fade Out
  •  Grow Out
  •  Shrink Out
  •  Slide Out to top, bottom, left, right
  •  Bounce Out to top, bottom, left, right, center
  •  Support custom

Layout the popup in the horizontal direction

  •  Left
  •  Right
  •  Center
  •  Left of center
  •  Right of center
  •  Support custom

Layout the popup in the vertical direction

  •  Top
  •  Bottom
  •  Center
  •  Above center
  •  Below center
  •  Support custom

Controlled whether to allow interaction with the underlying view

  •  Allow interaction with underlying view
  •  Don't allow interaction with underlying view
  •  Don't allow interaction with underlying view, dim background
  •  Don't allow interaction with underlying view, blur background
  •  Support custom

Others

  •  Complete Documentation

Requirements

  • iOS 8.0+ / macOS 10.13.6+
  • Xcode 10.1 (10B61) +
Bounce from Top & Bounce to BottomBounce from Top & Bounce to TopBounce in & Bounce outGrow in & Shrink outBounce from Bottom & Slide to BottomSlide from Bottom & Slide to Bottom
001_bounce_from_top&Bounce_to_bottom.gif002_bounce_from_top&bounce_to_top.gif003_bounce_in&bounce_out.gif004_grow_in&shrink_out.gif005_bounce_from_bottom&slide_to_bottom.gif006_slide_from_bottom&slide_to_bottom.gif

Example

To run the FFPopup project, clone the Repo, and start FFPopup in Xcode.

$ git clone https://github.com/JonyFang/FFPopup.git
$ cd FFPopup
$ cd Shell && sh install-bundle.sh && sh install-pods.sh && cd ..
$ open FFPopup.xcworkspace

Installation

There are three ways to use FFPopup in your project:

  • Installation with CocoaPods
  • Installation with Carthage
  • Manually install

CocoaPods

CocoaPods is a dependency manager, which automates and simplifies the process of using 3rd-party libraries like FFPopup in your projects. First, add the following line to your Podfile:

pod 'FFPopup'

If you want to use the latest features of FFPopup use normal external source dependencies.

pod 'FFPopup', :git => 'https://github.com/JonyFang/FFPopup.git'

This pulls from the master branch directly.

Second, install FFPopup into your project:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate FFPopup into your Xcode project using Carthage, specify it in your Cartfile:

github "JonyFang/FFPopup"

Run the following command to build the framework:

$ carthage update

Drag the built FFPopup.framework binaries from Carthage/Build/iOS into your application’s Xcode project.

On your application targets’ Build Phases settings tab, click the + icon and choose New Run Script Phase. Create a Run Script in which you specify your shell (ex: /bin/sh), add the following contents to the script area below the shell:

/usr/local/bin/carthage copy-frameworks

Add the following paths to the frameworks you want to use under Input Files.

$(SRCROOT)/Carthage/Build/iOS/FFPopup.framework

For an in depth guide, read on from Adding frameworks to an application

Manually

Alternatively you can directly add the FFPopup.h and FFPopup.m source files to your project.

  • Download the latest code version or add the repository as a git submodule to your git-tracked project.
  • Open your project in Xcode, then drag and drop FFPopup.h and FFPopup.m onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project.
  • Include FFPopup wherever you need it with #import "FFPopup.h".

Swift

Even though FFPopup is written in Objective-C, it can be used in Swift with no hassle. If you use CocoaPods add the following line to your Podfile:

use_frameworks!

If you added FFPopup manually, just add a bridging header file to your project with the FFPopup header included.

Usage

Import the library where you want to use it.

  • Objective-C
#import <FFPopup.h>

- (void)showPopup {
    FFPopup *popup = [FFPopup popupWithContentView:self.contentView showType:FFPopupShowType_BounceIn dismissType:FFPopupDismissType_ShrinkOut maskType:FFPopupMaskType_Dimmed dismissOnBackgroundTouch:YES dismissOnContentTouch:NO];
    FFPopupLayout layout = FFPopupLayoutMake(FFPopupHorizontalLayout_Center, FFPopupVerticalLayout_Center);
    [popup showWithLayout:layout];
}
  • Swift
import FFPopup

func showPopup() {
    let popup = FFPopup(contentView: self.contentView, showType: .bounceIn, dismissType: .shrinkOut, maskType: .dimmed, dismissOnBackgroundTouch: true, dismissOnContentTouch: false)
    let layout = FFPopupLayout(horizontal: .center, vertical: .center)
    popup.show(layout: layout)
}

Customization

1.FFPopupShowType

Animation transition for presenting contentView. Controlled how the popup will be presented.

The default value is FFPopupShowType_BounceInFromTop.

FFPopupShowType
FFPopupShowType_None
FFPopupShowType_FadeIn
FFPopupShowType_GrowIn
FFPopupShowType_ShrinkIn
FFPopupShowType_SlideInFromTop
FFPopupShowType_SlideInFromBottom
FFPopupShowType_SlideInFromLeft
FFPopupShowType_SlideInFromRight
FFPopupShowType_BounceIn
FFPopupShowType_BounceInFromTop
FFPopupShowType_BounceInFromBottom
FFPopupShowType_BounceInFromLeft
FFPopupShowType_BounceInFromRight

2.FFPopupDismissType

Animation transition for dismissing contentView. Controlled how the popup will be dismissed.

The default value is FFPopupDismissType_BounceOutToBottom.

FFPopupDismissType
FFPopupDismissType_None
FFPopupDismissType_FadeOut
FFPopupDismissType_GrowOut
FFPopupDismissType_ShrinkOut
FFPopupDismissType_SlideOutToTop
FFPopupDismissType_SlideOutToBottom
FFPopupDismissType_SlideOutToLeft
FFPopupDismissType_SlideOutToRight
FFPopupDismissType_BounceOut
FFPopupDismissType_BounceOutToTop
FFPopupDismissType_BounceOutToBottom
FFPopupDismissType_BounceOutToLeft
FFPopupDismissType_BounceOutToRight

3.FFPopupMaskType

Mask prevents background touches from passing to underlying views. Controlled whether to allow interaction with the underlying view.

The default value is FFPopupMaskType_Dimmed.

FFPopupMaskType
FFPopupMaskType_None
FFPopupMaskType_Clear
FFPopupMaskType_Dimmed

4.Other Properties

Property NameDescriptionDefault Value
dimmedMaskAlphaOverrides alpha value for dimmed mask.0.5
showInDurationOverrides animation duration for show in.0.15
dismissOutDurationOverrides animation duration for dismiss out.0.15
shouldDismissOnBackgroundTouchIf YES, the popup will dismiss when background is touched.YES
shouldDismissOnContentTouchIf YES, the popup will dismiss when content view is touched.NO

5.Blocks

/**
 A block to be executed when showing animation started.
 The default value is nil.
 */
@property (nonatomic, copy, nullable) void(^willStartShowingBlock)(void);

/**
 A block to be executed when showing animation finished.
 The default value is nil.
 */
@property (nonatomic, copy, nullable) void(^didFinishShowingBlock)(void);

/**
 A block to be executed when dismissing animation started.
 The default value is nil.
 */
@property (nonatomic, copy, nullable) void(^willStartDismissingBlock)(void);

/**
 A block to be executed when dismissing animation finished.
 The default value is nil.
 */
@property (nonatomic, copy, nullable) void(^didFinishDismissingBlock)(void);

6.Convenience Initializers

Create a new popup with custom values.

/**
 Convenience Initializers
 Create a new popup with `contentView`.
 */
+ (FFPopup *)popupWithContentView:(UIView *)contentView;

/**
 Convenience Initializers
 Create a new popup with custom values.
 
 @param contentView The view you want to appear in popup.
 @param showType    The default value is `FFPopupShowType_BounceInFromTop`.
 @param dismissType The default value is `FFPopupDismissType_BounceOutToBottom`.
 @param maskType    The default value is `FFPopupMaskType_Dimmed`.
 @param shouldDismissOnBackgroundTouch  The default value is `YES`.
 @param shouldDismissOnContentTouch     The default value is `NO`.
 */
+ (FFPopup *)popupWithContentView:(UIView *)contentView
                         showType:(FFPopupShowType)showType
                      dismissType:(FFPopupDismissType)dismissType
                         maskType:(FFPopupMaskType)maskType
         dismissOnBackgroundTouch:(BOOL)shouldDismissOnBackgroundTouch
            dismissOnContentTouch:(BOOL)shouldDismissOnContentTouch;

7.Showing the Popup

/**
 Show popup with center layout.
 `FFPopupVerticalLayout_Center` & `FFPopupHorizontalLayout_Center`
 Showing animation is determined by `showType`.
 */
- (void)show;

/**
 Show popup with specified layout.
 Showing animation is determined by `showType`.
 */
- (void)showWithLayout:(FFPopupLayout)layout;

/**
 Show and then dismiss popup after `duration`.
 If duration is `0.0` or `less`, it will be considered infinity.
 */
- (void)showWithDuration:(NSTimeInterval)duration;

/**
 Show popup with specified `layout` and then dismissed after `duration`.
 If duration is `0.0` or `less`, it will be considered infinity.
 */
- (void)showWithLayout:(FFPopupLayout)layout duration:(NSTimeInterval)duration;

/**
 Show popup at point in view's coordinate system.
 If view is nil, will use screen base coordinates.
 */
- (void)showAtCenterPoint:(CGPoint)point inView:(UIView *)view;

/**
 Show popup at point in view's coordinate system and then dismissed after duration.
 If view is nil, will use screen base coordinates.
 If duration is `0.0` or `less`, it will be considered infinity.
 */
- (void)showAtCenterPoint:(CGPoint)point inView:(UIView *)view duration:(NSTimeInterval)duration;

8.Dismissing the Popup

/**
 Dismiss popup.
 Use `dismissType` if animated is `YES`.
 */
- (void)dismissAnimated:(BOOL)animated;
 /**
 Dismiss all the popups in the app.
 */
+ (void)dismissAllPopups;

/**
 Dismiss the popup for contentView.
 */
+ (void)dismissPopupForView:(UIView *)view animated:(BOOL)animated;

/**
 Dismiss super popup.
 Iterate over superviews until you find a `FFPopup` and dismiss it.
 */
+ (void)dismissSuperPopupIn:(UIView *)view animated:(BOOL)animated;

TODO List

This is the to-do list for the FFPopup project. You can join us to become a contributor.

  •  Support blur option for background mask
  •  Support for keyboard show/hide
  •  Support for drag-to-dismiss

See the CONTRIBUTING file for contributing guidelines.

Live Demo

My app Time Card -Countdown (Never Forget Important Days) is using FFPopup. You can download it and try it on your multiple devices to experience the effect.

 

Download Details:

Author: JonyFang
Source Code: https://github.com/JonyFang/FFPopup 
License: MIT license

#swift #alert #objective-c #popup 

FFPopup: Presenting Custom Views As A Popup in iOS
Rupert  Beatty

Rupert Beatty

1673653500

StatusAlert: Display Apple System-like Self-hiding Status Alerts

StatusAlert is being sponsored by the following tool; please help to support us by takin a look and signing up to a free trial.

GitAds

StatusAlert is an iOS framework that displays status alerts similar to Apple's system self-hiding alerts. It is well suited for notifying user without interrupting user flow in iOS-like way.

It looks very similar to the alerts displayed in Podcasts, Apple Music and News apps. System StatusAlert

Features

  • System-like look and feel
  • Reduce transparency mode support
  • VoiceOver support
  • Safe Areas support
  • Universal (iPhone & iPad)
  • Objective-C support

Requirements

  • Xcode 9.0 or later
  • iOS 9.0 or later
  • Swift 3.2 or later

Installation

CocoaPods

To install StatusAlert using CocoaPods, add the following line to your Podfile:

pod 'StatusAlert', '~> 1.1.1'

Carthage

To install StatusAlert using Carthage, add the following line to your Cartfile:

github "LowKostKustomz/StatusAlert" ~> 1.1.1

Swift Package Manager

To install StatusAlert using Swift Package Manager add this to your dependencies in a Package.swift file:

dependencies: [
    .package(url: "https://github.com/LowKostKustomz/StatusAlert.git", .exact("1.1.1"))
]

Manual installation

You can also add this project:

  • as git submodule
  • simply download and copy source files to your project

Objective-C integration

StatusAlert is fully compatible with Objective-C. To import it to your project just add the following line:

@import StatusAlert;

Demo

Demo application is included in the StatusAlert workspace. To run it clone the repo.

Demo StatusAlert

Usage

// Importing framework
import StatusAlert

// Creating StatusAlert instance
let statusAlert = StatusAlert()
statusAlert.image = UIImage(named: "Some image name")
statusAlert.title = "StatusAlert title"
statusAlert.message = "Message to show beyond title"
statusAlert.canBePickedOrDismissed = isUserInteractionAllowed

// Presenting created instance
statusAlert.showInKeyWindow()

All the alert components (image, title, message) are optional, but at least one should be present. Otherwise show() method will be ignored.

IMPORTANT

The alert must be presented only from the main thread, otherwise application will crash with an appropriate error.

Customization

Wiki with more content and examples available

Different configurations

Present alert with any set of image, title and message

Vertical position

Display alert anywhere you want, either on the top, in the center or at the bottom of the view, and with any offset.

Appearance

You can customize a single alert's appearance via the StatusAlert's appearance property or for all alerts at once with StatusAlert.Appearance's common property

var titleFont: UIFont
var messageFont: UIFont
var tintColor: UIColor
var backgroundColor: UIColor
var blurStyle: UIBlurEffect.Style

Dismissal

Alert will hide itself after 2 seconds timeout.

You can change alert showing duration by setting alertShowingDuration property. You also can set canBePickedOrDismissed property to true. After that you will be able to dismiss the alert manually by tapping it and delay dismissal by long tapping the alert.

Apps Using StatusAlert

 
Bitxfy 

BitxfyScreenShot


NotifyMe

NotifyMeScreenShot

Feel free to submit pull request if you are using this framework in your apps.

Download Details:

Author: LowKostKustomz
Source Code: https://github.com/LowKostKustomz/StatusAlert 
License: MIT license

#swift #ios #apple #alert #ui #system 

StatusAlert: Display Apple System-like Self-hiding Status Alerts
Rupert  Beatty

Rupert Beatty

1673170080

Popovers: A Library to Present Popovers

Popovers

A library to present popovers.

  • Present any view above your app's main content.
  • Attach to source views or use picture-in-picture positioning.
  • Display multiple popovers at the same time with smooth transitions.
  • Supports SwiftUI, UIKit, and multitasking windows on iPadOS.
  • Highly customizable API that's super simple — just add .popover.
  • Drop-in replacement for iOS 14's Menu that works on iOS 13.
  • SwiftUI-based core for a lightweight structure. 0 dependencies.
  • It's 2022 — about time that popovers got interesting!

Showroom

AlertColorMenuTipStandard
AlertColorMenuTipStandard
TutorialPicture-in-PictureNotification
TutorialPicture in PictureNotification

Example

Includes ~20 popover examples. Download

Example app

Installation

Requires iOS 13+. Popovers can be installed through the Swift Package Manager (recommended) or Cocoapods.

Swift Package Manager 
Add the Package URL:
Cocoapods 
Add this to your Podfile:


 

https://github.com/aheze/Popovers


 

pod 'Popovers'

Usage

To present a popover in SwiftUI, use the .popover(present:attributes:view) modifier. By default, the popover uses its parent view as the source frame.

import SwiftUI
import Popovers

struct ContentView: View {
    @State var present = false
    
    var body: some View {
        Button("Present popover!") {
            present = true
        }
        .popover(present: $present) { /// here!
            Text("Hi, I'm a popover.")
                .padding()
                .foregroundColor(.white)
                .background(.blue)
                .cornerRadius(16)
        }
    }
}

In UIKit, create a Popover instance, then present with UIViewController.present(_:). You should also set the source frame.

import SwiftUI
import Popovers

class ViewController: UIViewController {
    @IBOutlet weak var button: UIButton!
    @IBAction func buttonPressed(_ sender: Any) {
        var popover = Popover { PopoverView() }
        popover.attributes.sourceFrame = { [weak button] in
            button.windowFrame()
        }
        
        present(popover) /// here!
    }
}

struct PopoverView: View {
    var body: some View {
        Text("Hi, I'm a popover.")
            .padding()
            .foregroundColor(.white)
            .background(.blue)
            .cornerRadius(16)
    }
}

Button 'Present popover!' with a popover underneath. 
 

Customization

🔖💠🔲🟩🟥🎾🛑👓👉🎈🔰

Customize popovers through the Attributes struct. Pretty much everything is customizable, including positioning, animations, and dismissal behavior.

SwiftUI 
Configure in the attributes parameter.
UIKit 
Modify the attributes property.


 

.popover(
    present: $present,
    attributes: {
        $0.position = .absolute(
            originAnchor: .bottom,
            popoverAnchor: .topLeft
        )
    }
) {
    Text("Hi, I'm a popover.")
}


 

var popover = Popover {
    Text("Hi, I'm a popover.")
}

popover.attributes.position = .absolute(
    originAnchor: .bottom,
    popoverAnchor: .topLeft
)

present(popover)

🔖 Tag • AnyHashable?

Tag popovers to access them later from anywhere. This is useful for updating existing popovers.

/// Set the tag.
$0.tag = "Your Tag"

/// Access it later.
let popover = popover(tagged: "Your Tag") /// Where `self` is a `UIView` or `UIViewController`.

/// If inside a SwiftUI View, use a `WindowReader`:
WindowReader { window in
    let popover = window.popover(tagged: "Your Tag")
}

Note: When you use the .popover(selection:tag:attributes:view:) modifier, this tag is automatically set to what you provide in the parameter.

💠 Position • Position

The popover's position can either be .absolute (attached to a view) or .relative (picture-in-picture). The enum's associated value additionally configures which sides and corners are used.

  • Anchors represent sides and corners.
  • For .absolute, provide the origin anchor and popover anchor.
  • For .relative, provide the popover anchors. If there's multiple, the user will be able to drag between them like a PIP.
Anchor Reference.absolute(originAnchor: .bottom, popoverAnchor: .topLeft).relative(popoverAnchors: [.right])

⬜ Source Frame • (() -> CGRect)

This is the frame that the popover attaches to or is placed within, depending on its position. This must be in global window coordinates. Because frames are can change so often, this property is a closure. Whenever the device rotates or some other bounds update happens, the closure will be called.

SwiftUI 
By default, the source frame is automatically set to the parent view. Setting this will override it.
UIKit 
It's highly recommended to provide a source frame, otherwise the popover will appear in the top-left of the screen.


 

$0.sourceFrame = {
    /** some CGRect here */
}


 

 /// use `weak` to prevent a retain cycle
attributes.sourceFrame = { [weak button] in
    button.windowFrame()
}

🔲 Source Frame Inset • UIEdgeInsets

Edge insets to apply to the source frame. Positive values inset the frame, negative values expand it.

AbsoluteRelative
Source view has padding around it, so the popover is offset down.Source view is inset, so the popover is brought more towards the center of the screen.

⏹ Screen Edge Padding • UIEdgeInsets

Global insets for all popovers to prevent them from overflowing off the screen. Kind of like a safe area. Default value is UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16).

🟩 Presentation • Presentation

This property stores the animation and transition that's applied when the popover appears.

/// Default values:
$0.presentation.animation = .easeInOut
$0.presentation.transition = .opacity

🟥 Dismissal • Dismissal

This property stores the popover's dismissal behavior. There's a couple sub-properties here.

/// Same thing as `Presentation`.
$0.dismissal.animation = .easeInOut
$0.dismissal.transition = .opacity

/// Advanced stuff! Here's their default values:
$0.dismissal.mode = .tapOutside
$0.dismissal.tapOutsideIncludesOtherPopovers = false
$0.dismissal.excludedFrames = { [] }
$0.dismissal.dragMovesPopoverOffScreen = true
$0.dismissal.dragDismissalProximity = CGFloat(0.25)

Mode: Configure how the popover should auto-dismiss. You can have multiple at the same time!

  • .tapOutside - dismiss the popover when the user taps outside it.
  • .dragDown - dismiss the popover when the user drags it down.
  • .dragUp - dismiss the popover when the user drags it up.
  • .none - don't automatically dismiss the popover.

Tap Outside Includes Other Popovers: Only applies when mode is .tapOutside. If this is enabled, the popover will be dismissed when the user taps outside, even when another presented popover is what's tapped. Normally when you tap another popover that's presented, the current one will not dismiss.

Excluded Frames: Only applies when mode is .tapOutside. When the user taps outside the popover, but the tap lands on one of these frames, the popover will stay presented. If you want multiple popovers, you should set the source frames of your other popovers as the excluded frames.

/// Set one popover's source frame as the other's excluded frame.
/// This prevents the the current popover from being dismissed before animating to the other one.

let popover1 = Popover { Text("Hello") }
popover1.attributes.sourceFrame = { [weak button1] in button1.windowFrame() }
popover1.attributes.dismissal.excludedFrames = { [weak button2] in [ button2.windowFrame() ] }

let popover2 = Popover { Text("Hello") }
popover2.attributes.sourceFrame = { [weak button2] in button2.windowFrame() }
popover2.attributes.dismissal.excludedFrames = { [weak button1] in [ button1.windowFrame() ] }

Drag Moves Popover Off Screen: Only applies when mode is .dragDown or .dragUp. If this is enabled, the popover will continue moving off the screen after the user drags.

Drag Dismissal Proximity: Only applies when mode is .dragDown or .dragUp. Represents the point on the screen that the drag must reach in order to auto-dismiss. This property is multiplied by the screen's height.

Diagram with the top 25% of the screen highlighted in blue.

🎾 Rubber Banding Mode • RubberBandingMode

Configures which axes the popover can "rubber-band" on when dragged. The default is [.xAxis, .yAxis].

  • .xAxis - enable rubber banding on the x-axis.
  • .yAxis - enable rubber banding on the y-axis.
  • .none - disable rubber banding.

🛑 Blocks Background Touches • Bool

Set this to true to prevent underlying views from being pressed.

Popover overlaid over some buttons. Tapping on the buttons has no effect.

👓 Accessibility • Accessibilityv1.2.0

Popovers is fully accessible! The Accessibility struct provides additional options for how VoiceOver should read out content.

/// Default values:
$0.accessibility.shiftFocus = true
$0.accessibility.dismissButtonLabel = defaultDismissButtonLabel /// An X icon wrapped in `AnyView?`

Shift Focus: If enabled, VoiceOver will focus the popover as soon as it's presented.

Dismiss Button Label: A button next to the popover that appears when VoiceOver is on. By default, this is an X circle.

VoiceOver highlights the popover, which has a X button next to id.

Tip: You can also use the accessibility escape gesture (a 2-fingered Z-shape swipe) to dismiss all popovers.

👉 On Tap Outside • (() -> Void)?

A closure that's called whenever the user taps outside the popover.

🎈 On Dismiss • (() -> Void)?

A closure that's called when the popover is dismissed.

🔰 On Context Change • ((Context) -> Void)?

A closure that's called whenever the context changed. The context contains the popover's attributes, current frame, and other visible traits.


 

Utilities

📘🧩🌃📖🏷📄

Popovers comes with some features to make your life easier.

📘 Menus

New in v1.3.0! The template Menu looks and behaves pretty much exactly like the system menu, but also works on iOS 13. It's also extremely customizable with support for manual presentation and custom views.

The system menu and Popovers' custom menu, side by side

SwiftUI (Basic)

struct ContentView: View {
    var body: some View {
        Templates.Menu {
            Templates.MenuButton(title: "Button 1", systemImage: "1.circle.fill") { print("Button 1 pressed") }
            Templates.MenuButton(title: "Button 2", systemImage: "2.circle.fill") { print("Button 2 pressed") }
        } label: { fade in
            Text("Present Menu!")
                .opacity(fade ? 0.5 : 1)
        }
    }
}

SwiftUI (Customized)

Templates.Menu(
    configuration: {
        $0.width = 360
        $0.backgroundColor = .blue.opacity(0.2)
    }
) {
    Text("Hi, I'm a menu!")
        .padding()

    Templates.MenuDivider()

    Templates.MenuItem {
        print("Item tapped")
    } label: { fade in
        Color.clear.overlay(
            AsyncImage(url: URL(string: "https://getfind.app/image.png")) {
                $0.resizable().aspectRatio(contentMode: .fill)
            } placeholder: {
                Color.clear
            }
        )
        .frame(height: 180)
        .clipped()
        .opacity(fade ? 0.5 : 1)
    }

} label: { fade in
    Text("Present Menu!")
        .opacity(fade ? 0.5 : 1)
}

SwiftUI (Manual Presentation)

struct ContentView: View {
    @State var present = false
    var body: some View {
        VStack {
            Toggle("Activate", isOn: $present)
                .padding()
                .background(.regularMaterial)
                .cornerRadius(12)
                .padding()
            
            Templates.Menu(present: $present) {
                Templates.MenuButton(title: "Button 1", systemImage: "1.circle.fill") { print("Button 1 pressed") }
                Templates.MenuButton(title: "Button 2", systemImage: "2.circle.fill") { print("Button 2 pressed") }
            } label: { fade in
                Text("Present Menu!")
                    .opacity(fade ? 0.5 : 1)
            }
        }
    }
}

UIKit (Basic)

class ViewController: UIViewController {
    @IBOutlet var label: UILabel!

    lazy var menu = Templates.UIKitMenu(sourceView: label) {
        Templates.MenuButton(title: "Button 1", systemImage: "1.circle.fill") { print("Button 1 pressed") }
        Templates.MenuButton(title: "Button 2", systemImage: "2.circle.fill") { print("Button 2 pressed") }
    } fadeLabel: { [weak self] fade in
        self?.label.alpha = fade ? 0.5 : 1
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        _ = menu /// Create the menu.
    }
}

UIKit (Customized)

class ViewController: UIViewController {
    @IBOutlet var label: UILabel!

    lazy var menu = Templates.UIKitMenu(
        sourceView: label,
        configuration: {
            $0.width = 360
            $0.backgroundColor = .blue.opacity(0.2)
        }
    ) {
        Text("Hi, I'm a menu!")
            .padding()

        Templates.MenuDivider()

        Templates.MenuItem {
            print("Item tapped")
        } label: { fade in
            Color.clear.overlay(
                AsyncImage(url: URL(string: "https://getfind.app/image.png")) {
                    $0.resizable().aspectRatio(contentMode: .fill)
                } placeholder: {
                    Color.clear
                }
            )
            .frame(height: 180)
            .clipped()
            .opacity(fade ? 0.5 : 1)
        }
    } fadeLabel: { [weak self] fade in
        UIView.animate(withDuration: 0.15) {
            self?.label.alpha = fade ? 0.5 : 1
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        _ = menu /// Create the menu.
    }
}

UIKit (Manual Presentation)

class ViewController: UIViewController {
    /// ...

    @IBAction func switchPressed(_ sender: UISwitch) {
        if menu.isPresented {
            menu.dismiss()
        } else {
            menu.present()
        }
    }
}
BasicCustomizedManual Presentation
Menu with 2 buttonsMenu with image and dividerManually activate the menu with a toggle switch

🧩 Animating Between Popovers

As long as the view structure is the same, you can smoothly transition from one popover to another.

SwiftUI 
Use the .popover(selection:tag:attributes:view:) modifier.
UIKit 
Get the existing popover using UIResponder.popover(tagged:), then call UIResponder.replace(_:with:).


 

struct ContentView: View {
    @State var selection: String?
    
    var body: some View {
        HStack {
            Button("Present First Popover") { selection = "1" }
            .popover(selection: $selection, tag: "1") {

                /// Will be presented when selection == "1".
                Text("Hi, I'm a popover.")
                    .background(.blue)
            }
            
            Button("Present Second Popover") { selection = "2" }
            .popover(selection: $selection, tag: "2") {

                /// Will be presented when selection == "2".
                Text("Hi, I'm a popover.")
                    .background(.green)
            }
        }
    }
}


 

@IBAction func button1Pressed(_ sender: Any) {
    var newPopover = Popover { Text("Hi, I'm a popover.").background(.blue) }
    newPopover.attributes.sourceFrame = { [weak button1] in button1.windowFrame() }
    newPopover.attributes.dismissal.excludedFrames = { [weak button2] in [button2.windowFrame()] }
    newPopover.attributes.tag = "Popover 1"
    
    if let oldPopover = popover(tagged: "Popover 2") {
        replace(oldPopover, with: newPopover)
    } else {
        present(newPopover) /// Present if the old popover doesn't exist.
    }
}
@IBAction func button2Pressed(_ sender: Any) {
    var newPopover = Popover { Text("Hi, I'm a popover.").background(.green) }
    newPopover.attributes.sourceFrame = { [weak button2] in button2.windowFrame() }
    newPopover.attributes.dismissal.excludedFrames = { [weak button1] in [button1.windowFrame()] }
    newPopover.attributes.tag = "Popover 2"
    
    if let oldPopover = popover(tagged: "Popover 1") {
        replace(oldPopover, with: newPopover)
    } else {
        present(newPopover)
    }
}
Smooth transition between popovers (from blue to green and back.

🌃 Background

You can put anything in a popover's background.

SwiftUI 
Use the .popover(present:attributes:view:background:) modifier.
UIKit 
Use the Popover(attributes:view:background:) initializer.


 

.popover(present: $present) {
    PopoverView()
} background: { /// here!
    Color.green.opacity(0.5)
}


 

var popover = Popover {
    PopoverView()
} background: { /// here!
    Color.green.opacity(0.5)
}

Green background over the entire screen, but underneath the popover

📖 Popover Reader

This reads the popover's context, which contains its frame, window, attributes, and various other properties. It's kind of like GeometryReader, but cooler. You can put it in the popover's view or its background.

.popover(present: $present) {
    PopoverView()
} background: {
    PopoverReader { context in
        Path {
            $0.move(to: context.frame.point(at: .bottom))
            $0.addLine(to: context.windowBounds.point(at: .bottom))
        }
        .stroke(Color.blue, lineWidth: 4)
    }
}
Line connects the bottom of the popover with the bottom of the screen

🏷 Frame Tags

Popovers includes a mechanism for tagging and reading SwiftUI view frames. You can use this to provide a popover's sourceFrame or excludedFrames. Also works great when combined with PopoverReader, for connecting lines with anchor views.

Text("This is a view")
    .frameTag("Your Tag Name") /// Adds a tag inside the window.

/// ...

WindowReader { window in
    Text("Click me!")
    .popover(
        present: $present,
        attributes: {
            $0.sourceFrame = window.frameTagged("Your Tag Name") /// Retrieves a tag from the window.
        }
    )
}

📄 Templates

Get started quickly with some templates. All of them are inside Templates with example usage in the example app.

  • AlertButtonStyle - a button style resembling a system alert.
  • VisualEffectView - lets you use UIKit blurs in SwiftUI.
  • Container - a wrapper view for the BackgroundWithArrow shape.
  • Shadow - an easier way to apply shadows.
  • BackgroundWithArrow - a shape with an arrow that looks like the system popover.
  • CurveConnector - an animatable shape with endpoints that you can set.
  • Menu - the system menu, but built from scratch.

Notes

State Re-Rendering

If you directly pass a variable down to the popover's view, it might not update. Instead, move the view into its own struct and pass down a Binding.

Yes 
The popover's view is in a separate struct, with $string passed down.
No 
The button is directly inside the view parameter and receives string.


 

struct ContentView: View {
    @State var present = false
    @State var string = "Hello, I'm a popover."

    var body: some View {
        Button("Present popover!") { present = true }
        .popover(present: $present) {
            PopoverView(string: $string) /// Pass down a Binding ($).
        }
    }
}

/// Create a separate view to ensure that the button updates.
struct PopoverView: View {
    @Binding var string: String

    var body: some View {
        Button(string) { string = "The string changed." }
        .background(.mint)
        .cornerRadius(16)
    }
}


 

struct ContentView: View {
    @State var present = false
    @State var string = "Hello, I'm a popover."

    var body: some View {
        Button("Present popover!") {
            present = true
        }
        .popover(present: $present) {

            /// Directly passing down the variable (without $) is unsupported.
            /// The button might not update.
            Button(string) { 
                string = "The string changed."
            }
            .background(.mint)
            .cornerRadius(16)
        }
    }
}

Supporting Multiple Screens • v1.1.0

Popovers comes with built-in support for multiple screens, but retrieving frame tags requires a reference to the hosting window. You can get this via WindowReader or PopoverReader's context.

WindowReader { window in 

}

/// If inside a popover's `view` or `background`, use `PopoverReader` instead.
PopoverReader { context in
    let window = context.window
}

Popover Hierarchy

Manage a popover's z-axis level by attaching .zIndex(_:) to its view. A higher index will bring it forwards.

Community

AuthorContributingNeed Help?
Popovers is made by aheze.All contributions are welcome. Just fork the repo, then make a pull request.Open an issue or join the Discord server. You can also ping me on Twitter. Or read the source code — there's lots of comments.

Apps Using Popovers

Find is an app that lets you find text in real life. Popovers is used for the quick tips and as a replacements for menus — download to check it out!

Find App 

If you have an app that uses Popovers, just make a PR or message me.

Download Details:

Author: aheze
Source Code: https://github.com/aheze/Popovers 
License: MIT license

#swift #ios #alert 

Popovers: A Library to Present Popovers
Rupert  Beatty

Rupert Beatty

1668134460

Alerttoast: Create Apple-like Alerts & Toasts using SwiftUI

AlertToast-SwiftUI

Present Apple-like alert & toast in SwiftUI

🌄 Example

ToastExample.gif

🔭 Overview

Currently in SwiftUI, the only way to inform the user about some process that finished for example, is by using Alert. Sometimes, you just want to pop a message that tells the user that something completed, or his message was sent. Apple doesn't provide any other method rather than using Alert even though Apple using all kinds of different pop-ups. The results are poor UX where the user would need to tap "OK/Dismiss" for every little information that he should be notified about.

Alert Toast is an open-source library in Github to use with SwiftUI. It allows you to present popups that don't need any user action to dismiss or to validate. Some great usage examples: Message Sent, Poor Network Connection, Profile Updated, Logged In/Out, Favorited, Loading and so on…

  • Built with pure SwiftUI.
  • 3 Display modes: Alert (pop at the center), HUD (drop from the top) and Banner (pop/slide from the bottom).
  • Complete, Error SystemImage, Image, Loading, and Regular (Only Text).
  • Supports Light & Dark Mode.
  • Works with any kind of view builder.
  • Localization support.
  • Font & Background customization.

If you like the project, don't forget to put star 🌟.

💻 Installation

Cocoapods

AlertToast Cocapods Website

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate AlertToast into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'AlertToast'

Swift Package Manager

The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

To integrate AlertToast into your Xcode project using Xcode 12, specify it in File > Swift Packages > Add Package Dependency...:

https://github.com/elai950/AlertToast.git, :branch="master"

For Xcode 13, please refer this article to install AlertToast


Manually

If you prefer not to use any of dependency managers, you can integrate AlertToast into your project manually. Put Sources/AlertToast folder in your Xcode project. Make sure to enable Copy items if needed and Create groups.

🧳 Requirements

  • iOS 13.0+ | macOS 11+
  • Xcode 12.0+ | Swift 5+

🛠 Usage

First, add import AlertToast on every swift file you would like to use AlertToast.

Then, use the .toast view modifier:

Parameters:

  • isPresenting: (MUST) assign a Binding<Bool> to show or dismiss alert.
  • duration: default is 2, set 0 to disable auto dismiss.
  • tapToDismiss: default is true, set false to disable.
  • alert: (MUST) expects AlertToast.

Usage example with regular alert

import AlertToast
import SwiftUI

struct ContentView: View{

    @State private var showToast = false

    var body: some View{
        VStack{

            Button("Show Toast"){
                 showToast.toggle()
            }
        }
        .toast(isPresenting: $showToast){

            // `.alert` is the default displayMode
            AlertToast(type: .regular, title: "Message Sent!")
            
            //Choose .hud to toast alert from the top of the screen
            //AlertToast(displayMode: .hud, type: .regular, title: "Message Sent!")
            
            //Choose .banner to slide/pop alert from the bottom of the screen
            //AlertToast(displayMode: .banner(.slide), type: .regular, title: "Message Sent!")
        }
    }
}

Complete Modifier Example

.toast(isPresenting: $showAlert, duration: 2, tapToDismiss: true, alert: {
   //AlertToast goes here
}, onTap: {
   //onTap would call either if `tapToDismis` is true/false
   //If tapToDismiss is true, onTap would call and then dismis the alert
}, completion: {
   //Completion block after dismiss
})

Alert Toast Parameters

AlertToast(displayMode: DisplayMode,
           type: AlertType,
           title: Optional(String),
           subTitle: Optional(String),
           style: Optional(AlertStyle))
           
//This is the available customizations parameters:
AlertStyle(backgroundColor: Color?,
            titleColor: Color?,
            subTitleColor: Color?,
            titleFont: Font?,
            subTitleFont: Font?)

Available Alert Types:

  • Regular: text only (Title and Subtitle).
  • Complete: animated checkmark.
  • Error: animated xmark.
  • System Image: name image from SFSymbols.
  • Image: name image from Assets.
  • Loading: Activity Indicator (Spinner).

Alert dialog view modifier (with default settings):

.toast(isPresenting: Binding<Bool>, duration: Double = 2, tapToDismiss: true, alert: () -> AlertToast , onTap: () -> (), completion: () -> () )

Simple Text Alert:

AlertToast(type: .regular, title: Optional(String), subTitle: Optional(String))

Complete/Error Alert:

AlertToast(type: .complete(Color)/.error(Color), title: Optional(String), subTitle: Optional(String))

System Image Alert:

AlertToast(type: .systemImage(String, Color), title: Optional(String), subTitle: Optional(String))

Image Alert:

AlertToast(type: .image(String), title: Optional(String), subTitle: Optional(String))

Loading Alert:

//When using loading, duration won't auto dismiss and tapToDismiss is set to false
AlertToast(type: .loading, title: Optional(String), subTitle: Optional(String))

You can add many .toast on a single view.

📖 Article

I wrote an article that contains more usage examples.

Medium - How to toast an alert in SwiftUI

👨‍💻 Contributors

All issue reports, feature requests, pull requests and GitHub stars are welcomed and much appreciated.



Download Details:

Author: elai950
Source Code: https://github.com/elai950/AlertToast 
License: MIT license

#swift #apple #alert #xcode #dialog #popup 

Alerttoast: Create Apple-like Alerts & Toasts using SwiftUI
Rupert  Beatty

Rupert Beatty

1667135220

SPAlert: Native Alert From Apple Music & Feedback

SPAlert

Popup from Apple Music & Feedback in AppStore. Contains Done, Heart, Error and other. Supports Dark Mode and SwiftUI. I tried to recreate Apple's alerts as much as possible. You can find these alerts in the AppStore after feedback and after you add a song to your library in Apple Music.

For get alert from switch silent mode, check library SPIndicator.

Installation

Ready for use on iOS 11+.

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

Once you have your Swift package set up, adding as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/ivanvorobei/SPAlert", .upToNextMajor(from: "4.2.0"))
]

CocoaPods:

CocoaPods is a dependency manager. For usage and installation instructions, visit their website. To integrate using CocoaPods, specify it in your Podfile:

pod 'SPAlert'

Manually

If you prefer not to use any of the dependency managers, you can integrate manually. Put Sources/SPAlert folder in your Xcode project. Make sure to enable Copy items if needed and Create groups.

Quick Start

For the best experience, I recommend presenting alerts by calling the class functions SPAlert. These functions are updated regularly and show the alerts as Apple way:

SPAlert.present(title: "Added to Library", preset: .done)

For using a custom image:

SPAlert.present(title: "Love", message: "We'll recommend more like this in For You", preset: .custom(UIImage.init(named: "heart")!))

For showing a simple text message:

SPAlert.present(message: "Something going wrong", haptic: .error)

Usage

Duration

To change the duration of present time, create an alert view and call present method with custom duration:

let alertView = SPAlertView(title: "Complete", preset: .done)
alertView.duration = 4
alertView.present()

If you don't want to dismiss alert in time, disable dismissInTime. After it, duration property will be ignored.

alertView.dismissInTime = false

In this case, you should dismiss the alert manually.

Dismiss

If you tap the alert, it will disappear. This can be disabled:

alertView.dismissByTap = false

Also, you can manually dismiss all alerts, simply call this:

SPAlert.dismiss()

Layout

For customise layout and margins, use layout property. You can manage margins for each side, icon size and space between image and titles:

alertView.layout.iconSize = .init(width: 24, height: 24)
alertView.layout.margins.top = 12
alertView.layout.spaceBetweenIconAndTitle = 8

Haptic

To manage haptic, you should pass it in present method:

alertView.present(duration: 1.5, haptic: .success, completion: nil)

You can remove duration and completion, because they have default values.

Spinner

I added the preset .spinner, to use it simply call this:

let alertView = SPAlertView(title: "Please, wait", preset: .spinner)
alertView.present()

By default this preset dismissInTime is disabled and the alert needs to be manually dismissed. You can do it only for one view or dismiss all alerts:

// For one alert
alertView.dismiss()

// For all alerts
SPAlert.dismiss()

Colors

For change color of icon, simple set tint color for any preset:

alertView.iconView?.tintColor = .systemRed

//If you set custom image, don't forget set rendering mode:
UIImage(systemName: "pencil.and.outline")!.withRenderingMode(.alwaysTemplate)

Global Appearance

Also you can change some default values for alerts. For example you can change default duration and corner radius for alert with next code:

SPAlertView.appearance().duration = 2
SPAlertView.appearance().cornerRadius = 12

It will apply to all alerts. I recommend setting it in the app delegate, but you can change it in runtime.

SwiftUI

Use like system alert only show message tips:

Button("Show alert") {
    showAlert = true
}.SPAlert(isPresent: $showAlert, message: "this is message only")

or show message, title, image and other configuration:

Button("Show alert") {
    showAlert = true
}.SPAlert(
    isPresent: $showAlert, 
    title: "Alert title", 
    message: "Alert message",
    duration: 2.0, 
    dismissOnTap: false, 
    preset: .custom(UIImage(systemName: "heart")!), 
    haptic: .success, 
    layout: .init(), 
    completion: {
        print("Alert is destory")
    })

Russian Community

Я веду телеграм-канал, там публикую новости и туториалы.
С проблемой помогут в чате.

Видео-туториалы выклыдываю на YouTube:

Tutorials on YouTube

Download Details:

Author: ivanvorobei
Source Code: https://github.com/ivanvorobei/SPAlert 
License: MIT license

#swift #ios #apple #alert 

SPAlert: Native Alert From Apple Music & Feedback
Rupert  Beatty

Rupert Beatty

1666763880

A Great & Customizable Alert That Can Substitute UIAlertController

PMAlertController

PMAlertController is a small library that allows you to substitute Apple's uncustomizable UIAlertController, with a beautiful and totally customizable alert that you can use in your iOS app. Enjoy!

Icon

Features


  •  Header View
  •  Header Image (Optional)
  •  Title
  •  Description message
  •  Customizations: fonts, colors, dimensions & more
  •  1, 2 buttons (horizontally) or 3+ buttons (vertically)
  •  Closure when a button is pressed
  •  Text Fields support
  •  Similar implementation to UIAlertController
  •  Cocoapods
  •  Carthage
  •  Animation with UIKit Dynamics
  •  Objective-C compatibility
  •  Swift 4, Swift 4.2 & Swift 5 support
  •  Swift Package Manager

Requirements


  • iOS 9.0+
  • Xcode 10+

CocoaPods


CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate PMAlertController into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

pod 'PMAlertController'

Then, run the following command:

$ pod install

Carthage


Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate PMAlertController into your Xcode project using Carthage, specify it in your Cartfile:

github "pmusolino/PMAlertController"

Run carthage update to build the framework and drag the built PMAlertController.framework into your Xcode project.

Manually


  1. Download and drop /Library folder in your project.
  2. Congratulations!

Usage


The usage is very similar to UIAlertController. PMAlertController has two styles: Alert & Walkthrough.

Alert Style: with this style, the alert has the width of 270 points, like Apple's UIAlertController.

Walkthrough Style: with walkthrough, the alert has the width of the screen minus 18 points from the left and the right bounds. This mode is intended to be used before authorization requests like the ones for location, push notifications and more.

Show a simple alert with two buttons and one textfield

//This code works with Swift 5

let alertVC = PMAlertController(title: "A Title", description: "My Description", image: UIImage(named: "img.png"), style: .alert)

alertVC.addAction(PMAlertAction(title: "Cancel", style: .cancel, action: { () -> Void in
            print("Capture action Cancel")
        }))

alertVC.addAction(PMAlertAction(title: "OK", style: .default, action: { () in
            print("Capture action OK")
        }))

alertVC.addTextField { (textField) in
            textField?.placeholder = "Location..."
        }

self.present(alertVC, animated: true, completion: nil)

Swift compatibility

If you use Swift 5.0 or higher, you can use the latest release.

If you use Swift 4, you can use the release 3.5.0.

If you use Swift 3, you can use the release 2.1.3.

If you use Swift 2.3, you can use the release 1.1.0

If you use Swift 2.2, you can use the release 1.0.5

Third Party Bindings

React Native

You may now use this library with React Native via the module here

Contributing

  • If you need help or you'd like to ask a general question, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Acknowledgements

Made with ❤️ by Paolo Musolino.

Follow me on:

💼 Linkedin

🤖 Twitter

🌇 Instagram

👨🏼‍🎤 Facebook


Download Details:

Author: pmusolino
Source Code: https://github.com/pmusolino/PMAlertController 
License: MIT license

#swift #alert #modal #dialog 

A Great & Customizable Alert That Can Substitute UIAlertController
Rupert  Beatty

Rupert Beatty

1666228680

Siren: Notify Users When A New Version Of Your App is Available

Siren 🚨

Notify users when a new version of your app is available and prompt them to upgrade.


Meta

About

Siren checks a user's currently installed version of your iOS app against the version that is currently available in the App Store.

If a new version is available, a language localized alert can be presented to the user informing them of the newer version, and giving them the option to update the application. Alternatively, Siren can notify your app through alternative means, such as a custom user interface.

Siren is built to work with the Semantic Versioning system.

  • Canonical Semantic Versioning uses a three number versioning system (e.g., 1.0.0)
  • Siren also supports two-number versioning (e.g., 1.0) and four-number versioning (e.g., 1.0.0.0)

Features

Current Features


Screenshots

  • The left picture forces the user to update the app.
  • The center picture gives the user the option to update the app.
  • The right picture gives the user the option to skip the current update.
  • These options are controlled by the Rules.AlertType enum.

Ports

  • Objective-C (iOS)
    • Harpy
    • Siren was ported from Harpy, as Siren and Harpy are maintained by the same developer.
    • As of December 2018, Harpy has been deprecated in favor of Siren.
  • Java (Android)
  • React Native (iOS)

Installation and Integration

Installation Instructions

Swift VersionBranch NameWill Continue to Receive Updates?
5.5+masterYes
5.1-5.4swift5.4No
5.0swift5.0No
4.2swift4.2No
4.1swift4.1No
3.2swift3.2No
3.1swift3.1No
2.3swift2.3No

CocoaPods

pod 'Siren' # Swift 5.5+
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift5.4' # Swift 5.1-5.4
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift5.0' # Swift 5.0
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift4.2' # Swift 4.2
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift4.1' # Swift 4.1
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift3.2' # Swift 3.2
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift3.1' # Swift 3.1
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift2.3' # Swift 2.3

Swift Package Manager

.Package(url: "https://github.com/ArtSabintsev/Siren.git", majorVersion: 6)

Implementation Examples

Implementing Siren is as easy as adding two lines of code to your app in either AppDelegate.swift or SceneDelegate.swift:

AppDelegate.swift Example

import Siren // Line 1
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        window?.makeKeyAndVisible()

    Siren.shared.wail() // Line 2

        return true
    }
}

SceneDelegate.swift Example

import Siren // Line 1
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        window?.makeKeyAndVisible()

    Siren.shared.wail() // Line 2

        return true
    }
}

Siren also has plenty of customization options. All examples can be found in the Example Project's AppDelegate file. Uncomment the example you'd like to test.


Device-Specific Checks

Localization

Siren is localized for the following languages:

Arabic, Armenian, Basque, Chinese (Simplified and Traditional), Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hebrew, Hungarian, Indonesian, Italian, Japanese, Korean, Latvian, Lithuanian, Malay, Norwegian (Bokmål), Persian (Afghanistan, Iran, Persian), Polish, Portuguese (Brazil and Portugal), Romanian, Russian, Serbian (Cyrillic and Latin), Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian, Urdu, Vietnamese

If your user's device is set to one of the supported locales, an update message will appear in that language. If a locale is not supported, than the message will appear in English.

You may want the update dialog to always appear in a certain language, ignoring the user's device-specific setting. You can enable it like so:

// In this example, we force the `Russian` language.
Siren.shared.presentationManager = PresentationManager(forceLanguageLocalization: .russian)

Device Compatibility

If an app update is available, Siren checks to make sure that the version of iOS on the user's device is compatible with the one that is required by the app update. For example, if a user has iOS 11 installed on their device, but the app update requires iOS 12, an alert will not be shown. This takes care of the false positive case regarding app updating.


Testing

Testing Siren Locally

Temporarily change the version string in Xcode (within the .xcodeproj file) to an older version than the one that's currently available in the App Store. Afterwards, build and run your app, and you should see the alert.

If you currently don't have an app in the store, change your bundleID to one that is already in the store. In the sample app packaged with this library, we use Facebook's Bundle ID: com.facebook.Facebook.

Words of Caution

Occasionally, the iTunes JSON will update faster than the App Store CDN, meaning the JSON may state that the new version of the app has been released, while no new binary is made available for download via the App Store. It is for this reason that Siren will, by default, wait 1 day (24 hours) after the JSON has been updated to prompt the user to update. To change the default setting, please modify the value of showAlertAfterCurrentVersionHasBeenReleasedForDays.


App Submission

App Store Review

The App Store reviewer will not see the alert. The version in the App Store will always be older than the version being reviewed.

Phased Releases

In 2017, Apple announced the ability to rollout app updates gradually (a.k.a. Phased Releases). Siren will continue to work as it has in the past, presenting an update modal to all users. If you opt-in to a phased rollout for a specific version, you have a few choices:

  • You can leave Siren configured as normal. Phased rollout will continue to auto-update apps. Since all users can still manually update your app directly from the App Store, Siren will ignore the phased rollout and will prompt users to update.
  • You can set showAlertAfterCurrentVersionHasBeenReleasedForDays to 7, and Siren will not prompt any users until the latest version is 7 days old, after the phased rollout is complete.
  • You can remotely disable Siren until the rollout is done using your own API / backend logic.

Attribution

Special Thanks

A massive shout-out and thank you goes to the following folks:

  • Aaron Brager for motivating me and assisting me in building the initial proof-of-concept of Siren (based on Harpy) back in 2015. Without him, Siren may never have been built.
  • All of Harpy's Contributors for helping building the feature set from 2012-2015 that was used as the basis for the first version of Siren.
  • All of Siren's Contributors for helping make Siren as powerful and bug-free as it currently is today.

Creator

Arthur Ariel Sabintsev

Download Details:

Author: ArtSabintsev
Source Code: https://github.com/ArtSabintsev/Siren 
License: MIT license

#swift #alert #update 

Siren: Notify Users When A New Version Of Your App is Available

A Simple Plugin to Present Native Alerts in Your Flutter App

flutter_platform_alert

2021 and onwards © Weizhong Yang a.k.a zonble.

A simple plugin to present native alerts, including playing alert sounds and showing alert dialogs on various platforms including iOS, Android, Windows, macOS and Linux.

It uses following API to show play alert sound.

It uses following API to show alert dialogs.

The package was developed and tested on

  • iOS 15
  • Android 11
  • macOS 11 Big Sur and mac OS 12 Monterey / Xcode 13
  • Windows 10 / Visual Studio Community 2019
  • Ubuntu 21.10

Getting Started

  • Add the dependency to your pubspec.yaml file by flutter pub add flutter_platform_alert.
  • Run flutter pub get.

To play platform alert sound.

import 'package:flutter_platform_alert/flutter_platform_alert.dart';
await FlutterPlatformAlert.playAlertSound();

To show a platform alert dialog.

import 'package:flutter_platform_alert/flutter_platform_alert.dart';
await FlutterPlatformAlert.playAlertSound();

final clickedButton = await FlutterPlatformAlert.showAlert(
    windowTitle: 'This ia title',
    text: 'This is body',
    alertStyle: AlertButtonStyle.yesNoCancel,
    iconStyle: IconStyle.information,
);

To show an alert dialog with custom button titles:

import 'package:flutter_platform_alert/flutter_platform_alert.dart';
await FlutterPlatformAlert.playAlertSound();

final clickedButton = await FlutterPlatformAlert.showCustomAlert(
    windowTitle: 'This ia title',
    text: 'This is body',
    positiveButtonTitle: "Positive",
    negativeButtonTitle: "Negative",
    neutralButtonTitle: "Neutral",
    additionalWindowTitleOnWindows: 'Window title',
    showAsLinksOnWindows: true);

Platform Alert Dialogs

Alert Styles

When calling showCustomAlert, you can assign any button titles and use up to three buttons. Once there is no button title specified, it falls back to only an "OK" button.

When calling showAlert, you can specify the buttons listed in the alert dialog by passing alertStyle argument. The package follows the API design on Windows (see the reference of MessageBox win32 API), and it provides following styles:

  • Abort, retry and ignore
  • Cancel, try again and continue
  • OK
  • OK and cancel
  • Retry and cancel
  • Yes and no
  • Yes, no, and cancel

Since each platform has its own conventions, the order of these buttons are not guaranteed to be the same.

Icon Styles

The package also follow the API design of MessageBox on Windows to add icons to the alert dialogs (see the link above). There are several different icons styles but actually four:

  • No icon
  • Warning icon
  • Information icon
  • Question icon

Please note that these icons are not available on iOS and Android.

Themes/Dark or Light Mode

On iOS and macOS, the alert dialogs follows the dark/light mode settings on users' system. On Linux, the alert dialogs are rendered with current GTK theme. On Windows, they are always in light mode even you choose to use dark mode on Windows 10 and Windows 11.

On Android, the alert dialog uses the default theme of Material design (as Theme.Material.Dialog.Alert).

Localization

Since the plugin calls native API, if you want to localize buttons like "OK", "Cancel" and so on on Platforms like iOS, macOS and Linux, you have to do some works in your app.

  • To localize the button titles on iOS and macOS, add "Localizable.strings" or "Localizable.stringsdict" files in your Xcode project. Visit Apple's official page for localization for further information.
  • On Linux, we use gettext to localize apps. Please update the PO files in your projects once you integrate the plugin.

Android apps embeds resources for localized strings. The localized strings files for the project are located under android/src/main/res. Once you need to add new languages, just fork the project and put your files under the folder.

On Windows, the buttons on the message boxes will be in the Windows system language.

License

The package in released under MIT License.

Screenshots

iOS 15 in Simulator

iOS

Android 11 on Samsung phone

Android

macOS 12 Monterey

macOS

Windows 10 with MessageBox API

Windows

Windows 11 with TaskDialogIndirect API

Windows

Windows 11 with TaskDialogIndirect API that shows buttons as links

Windows

Ubuntu 21.10

linux

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add flutter_platform_alert

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  flutter_platform_alert: ^0.3.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:flutter_platform_alert/flutter_platform_alert.dart'; 

example/lib/main.dart

// ignore_for_file: avoid_print

import 'dart:io';

import 'package:flutter/material.dart' hide MenuItem;
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
    await windowManager.ensureInitialized();
  }

  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TrayListener, WindowListener {
  @override
  void initState() {
    if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
      // These are not supported on iOS and Android.
      trayManager.addListener(this);
      windowManager.addListener(this);
      _init();
    }
    super.initState();
  }

  @override
  void dispose() {
    trayManager.removeListener(this);
    windowManager.removeListener(this);
    super.dispose();
  }

  void _init() async {
    await trayManager.setIcon(
      Platform.isWindows
          ? 'images/tray_icon_original.ico'
          : 'images/tray_icon_original.png',
    );
    List<MenuItem> items = [
      MenuItem(
        key: 'show_window',
        label: 'Show Window',
      ),
      MenuItem(
        key: 'hide_window',
        label: 'Hide Window',
      ),
      MenuItem(
        key: 'show_alert_ok',
        label: 'Show OK',
      ),
      MenuItem.separator(),
      MenuItem(
        key: 'exit_app',
        label: 'Exit App',
      ),
    ];
    final menu = Menu(items: items);
    await trayManager.setContextMenu(menu);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: const Text('Flutter Platform Alert')),
            body: ListView(children: [
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text('Play Alert Sounds',
                    style: Theme.of(context).textTheme.headline6),
              ),
              ListTile(
                  onTap: () async {
                    await FlutterPlatformAlert.playAlertSound();
                  },
                  title: const Text('Play Alert Sound (Default)')),
              ListTile(
                  onTap: () async {
                    await FlutterPlatformAlert.playAlertSound(
                      iconStyle: IconStyle.exclamation,
                    );
                  },
                  title: const Text('Play Alert Sound (exclamation)')),
              ListTile(
                  onTap: () async {
                    await FlutterPlatformAlert.playAlertSound(
                      iconStyle: IconStyle.error,
                    );
                  },
                  title: const Text('Play Alert Sound (error)')),
              const Divider(),
              Padding(
                padding: const EdgeInsets.all(14.0),
                child: Text('Standard Alert with Styles',
                    style: Theme.of(context).textTheme.headline6),
              ),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                      windowTitle: '白日依山盡 黃河入海流',
                      text: '芋頭西米露 保力達蠻牛',
                      iconStyle: IconStyle.exclamation,
                      alertStyle: AlertButtonStyle.abortRetryIgnore,
                      options: FlutterPlatformAlertOption(
                        preferMessageBoxOnWindows: true,
                      ),
                    );
                    print(result);
                  },
                  title: const Text('Show non-ascii characters')),
              const Divider(),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                      windowTitle: 'This ia title',
                      text: 'This is body',
                      iconStyle: IconStyle.warning,
                    );
                    print(result);
                  },
                  title: const Text('Show warning style')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                      windowTitle: 'This ia title',
                      text: 'This is body',
                      iconStyle: IconStyle.information,
                    );
                    print(result);
                  },
                  title: const Text('Show information style')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                      windowTitle: 'This ia title',
                      text: 'This is body',
                      iconStyle: IconStyle.error,
                    );
                    print(result);
                  },
                  title: const Text('Show error style')),
              const Divider(),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title', text: 'This is body');
                    print(result);
                  },
                  title: const Text('Show OK')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.okCancel);
                    print(result);
                  },
                  title: const Text('Show OK/Cancel')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.abortRetryIgnore);
                    print(result);
                  },
                  title: const Text('Show Abort/Retry/Ignore')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.cancelTryContinue);
                    print(result);
                  },
                  title: const Text('Show Cancel/Try/Continue')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.retryCancel);
                    print(result);
                  },
                  title: const Text('Show Retry/Cancel')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.yesNo);
                    print(result);
                  },
                  title: const Text('Show Yes/No')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showAlert(
                        windowTitle: 'This ia title',
                        text: 'This is body',
                        alertStyle: AlertButtonStyle.yesNoCancel);
                    print(result);
                  },
                  title: const Text('Show Yes/No/Cancel')),
              const Divider(),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text('Custom Alerts',
                    style: Theme.of(context).textTheme.headline6),
              ),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showCustomAlert(
                      windowTitle: 'This ia title',
                      text: 'This is body',
                      positiveButtonTitle: "Positive",
                      negativeButtonTitle: "Negative",
                      neutralButtonTitle: "Neutral",
                      iconPath: Platform.isWindows
                          ? 'images/tray_icon_original.ico'
                          : 'images/tray_icon_original.png',
                      options: FlutterPlatformAlertOption(
                          additionalWindowTitleOnWindows: 'Window title',
                          showAsLinksOnWindows: false),
                    );
                    print(result);
                  },
                  title: const Text('Show Positive/Negative/Neutral')),
              ListTile(
                  onTap: () async {
                    final result = await FlutterPlatformAlert.showCustomAlert(
                      windowTitle: 'This ia title',
                      text: 'This is body',
                      positiveButtonTitle: "Positive",
                      negativeButtonTitle: "Negative",
                      neutralButtonTitle: "Neutral",
                      options: FlutterPlatformAlertOption(
                          additionalWindowTitleOnWindows: 'Window title',
                          showAsLinksOnWindows: true),
                    );
                    print(result);
                  },
                  title: const Text(
                      'Show Positive/Negative/Neutral (as links on windows)')),
            ])));
  }

  @override
  void onTrayMenuItemClick(MenuItem menuItem) async {
    switch (menuItem.key) {
      case 'show_window':
        await windowManager.show();
        await windowManager.setSkipTaskbar(false);
        break;
      case 'hide_window':
        await windowManager.hide();
        await windowManager.setSkipTaskbar(true);
        break;
      case 'show_alert_ok':
        final result = await FlutterPlatformAlert.showAlert(
            windowTitle: 'This ia title', text: 'This is body');
        print(result);
        break;
      default:
        break;
    }
  }

  @override
  void onTrayIconMouseDown() {
    trayManager.popUpContextMenu();
  }
} 

Download Details:

Author: zonble

Source Code: https://github.com/zonble/flutter_platform_alert

#flutter #alert 

A Simple Plugin to Present Native Alerts in Your Flutter App
Hollie  Ratke

Hollie Ratke

1604278800

North Korea-Backed Spy Group Poses as Reporters in Spearphishing Attacks, Feds Warn

The North Korean advanced persistent threat (APT) group known as Kimsuky is actively attacking commercial-sector businesses, often by posing as South Korean reporters, according to an alert from the U.S. Cybersecurity and Infrastructure Security Agency (CISA).

Kimsuky (a.k.a. Hidden Cobra) has been operating as a cyberespionage group since 2012 under the auspices of the regime in Pyongyang. Its mission is global intelligence gathering, CISA noted, which usually starts with spearphishing emails, watering-hole attacks, torrent shares and malicious browser extensions, in order to gain an initial foothold in target networks.

Primary targets include think-tanks, and diplomatic and high-level organizations in Japan, South Korea and the United States, with a focus on foreign policy and national-security issues related to the Korean peninsula, nuclear policy and sanctions, CISA added. It also targets the cryptocurrency industry.

In recent campaigns seen over the summer, the group ultimately sent malicious attachments embedded in spearphishing emails to gain initial access to victim organizations, according to an analysis, published on Tuesday. But the malicious content was deployed only after several initial exchanges with the target meant to build trust.

“Posing as South Korean reporters, Kimsuky exchanged several benign interview-themed emails with their intended target to ostensibly arrange an interview date and possibly build rapport,” according to CISA. “The emails contained the subject line, ‘Skype Interview requests of [redacted TV show] in Seoul,’ and began with a request to have the recipient appear as a guest on the show. The APT group invited the targets to a Skype interview on the topic of inter-Korean issues and denuclearization negotiations on the Korean Peninsula.”

After a recipient agreed to an interview, Kimsuky sent a subsequent email with a malicious document. And when the date of the interview got closer, the purported “reporter” sent an email canceling the interview.

After obtaining initial access, the APT group ultimately deployed the BabyShark malware and PowerShell or the Windows Command Shell for execution.

“This is another example of the seriousness of the modern cybercrime world and the resources behind them,” said Erich Kron, security awareness advocate at KnowBe4, via email. “With billions of dollars at stake every year and with warfare expanding to the digital realm in such a large way, it is no surprise that nation-states are involved. The days of thick manila envelopes full of papers, traditional dossiers on people or stealthy microfilm cameras whisking away our information are gone. Now, it is all a bunch of ones and zeros in easily searched databases.”

#government #malware #web security #active campaigns #alert #analysis #babyshark #cisa #espionage #hidden cobra #kimsuky #malware #north korea #reporters #south korea #spyware

North Korea-Backed Spy Group Poses as Reporters in Spearphishing Attacks, Feds Warn
Ron  Cartwright

Ron Cartwright

1602968400

Election Systems Under Attack via Microsoft Zerologon Exploits

U.S. government officials have warned that advanced persistent threat actors (APTs) are now leveraging Microsoft’s severe privilege-escalation flaw, dubbed “Zerologon,” to target elections support systems.

Days after Microsoft sounded the alarm that an Iranian nation-state actor was actively exploiting the flaw (CVE-2020-1472), the Cybersecurity Infrastructure Security Agency (CISA) and the Federal Bureau of Investigation (FBI) published a joint advisory warning of further attacks.

The advisory details how attackers are chaining together various vulnerabilities and exploits – including using VPN vulnerabilities to gain initial access and then Zerologon as a post-exploitation method – to compromise government networks.

“This recent malicious activity has often, but not exclusively, been directed at federal and state, local, tribal and territorial (SLTT) government networks,” according to the security advisory. “Although it does not appear these targets are being selected because of their proximity to elections information, there may be some risk to elections information housed on government networks.”

With the U.S. November presidential elections around the corner – and cybercriminal activity subsequently ramping up to target election infrastructure and presidential campaigns – election security is top of mind. While the CISA and FBI’s advisory did not detail what type of elections systems were targeted, it did note that there is no evidence to support that the “integrity of elections data has been compromised.”

Microsoft released a patch for the Zerologon vulnerability as part of its August 11, 2020 Patch Tuesday security updates. Exploiting the bug allows an unauthenticated attacker, with network access to a domain controller, to completely compromise all Active Directory identity services, according to Microsoft.

Despite a patch being issued, many companies have not yet applied the patches to their systems – and cybercriminals are taking advantage of that in a recent slew of government-targeted attacks.

The CISA and FBI warned that various APT actors are commonly using a Fortinet vulnerability to gain initial access to companies. That flaw (CVE-2018-13379) is a path-traversal glitch in Fortinet’s FortiOS Secure Socket Layer (SSL) virtual private network (VPN) solution. While the flaw was patched in April 2019, exploitation details were publicized in August 2019, opening the door for attackers to exploit the error.

Other initial vulnerabilities being targeted in the attacks include ones in Citrix NetScaler (CVE-2019-19781), MobileIron (CVE-2020-15505), Pulse Secure (CVE-2019-11510), Palo Alto Networks (CVE-2020-2021) and F5 BIG-IP (CVE-2020-5902).

After exploiting an initial flaw, attackers are then leveraging the Zerologon flaw to escalate privileges, researchers said. They then use legitimate credentials to log in via VPN or remote-access services, in order to maintain persistence.

#critical infrastructure #vulnerabilities #web security #alert #apts #chaining #cisa #citrix netscaler #cve-2018-13379 #cve-2019-11510 #cve-2019-19781 #cve-2020-1472 #cve-2020-15505 #cve-2020-2021 #cve-2020-5902 #election security #election systems #exploit chain #f5 big-ip #fbi #government attacks #microsoft #mobileiron #palo alto networks #pulse secure #vpn #warning #zerologon

Election Systems Under Attack via Microsoft Zerologon Exploits
Steve Griffith

Steve Griffith

1598884238

alert, confirm, and prompt dialogs with JavaScript

https://www.youtube.com/watch?v=xXwSJGYqeIQ

How to create modal dialogs with the alert, confirm and prompt commands in JavaScript

#javascript #modal #alert #confirm #prompt #web-development

alert, confirm, and prompt dialogs with JavaScript
Hollie  Ratke

Hollie Ratke

1597683600

NSA Urgently Warns on Industrial Cyberattacks, Triconex Critical Bug

The U.S. National Security Agency (NSA) and the Cybersecurity and Infrastructure Security Agency (CISA) have issued an alert warning that adversaries could be targeting critical infrastructure across the U.S.

Separately, ICS-CERT issued an advisory on a critical security bug in the Schneider Electric Triconex TriStation and Tricon Communication Module. These safety instrumented system (SIS) controllers are responsible for shutting down plant operations in the event of a problem and act as an automated safety defense for industrial facilities, designed to prevent equipment failure and catastrophic incidents such as explosions or fire. They’ve been targeted in the past, in the TRITON attack of 2017.

“Over recent months, cyber-actors have demonstrated their continued willingness to conduct malicious cyber-activity against critical infrastructure (CI) by exploiting internet-accessible operational technology (OT) assets,” said the NSA/CISA joint advisory, released on Thursday. “Due to the increase in adversary capabilities and activity, the criticality to U.S. national security and way of life and the vulnerability of OT systems, civilian infrastructure makes attractive targets for foreign powers attempting to do harm to U.S. interests or retaliate for perceived U.S. aggression.”

Vulnerable OT Systems

The advisory goes on to point out that OT systems often consist of legacy equipment that was never designed to be connected to the internet nor defend against malicious cyberactivities. At the same time, more and more utilities, petrochemical installations, factories and so on are looking to increase remote operations. This means conducting various activities over the web using an IT network to connect to the OT side, enabling monitoring, instrumentation and control, OT asset management/maintenance, and in some cases, process operations and maintenance.

Generally, adversaries are using spearphishing efforts to obtain initial access to the organization’s IT network, before pivoting to the OT network, the advisory added.

“Combined with readily available information that identifies OT assets connected via the internet (e.g., Shodan, Kamerka), are creating a ‘perfect storm’ of easy access to unsecured assets, use of common, open-source information about devices, and an extensive list of exploits deployable via common exploit frameworks,” the agencies warned.

The NSA/CISA advisory also detailed that in the wild, several cyberattack attempts have been observed. These include attempts to: Deploy of commodity ransomware on both IT and OT networks; communicate with controllers and downloading modified control logic; use vendor engineering software and program downloads; and modify control logic and parameters on programmable logic controllers (PLCs). PLCs are responsible for directly reading and manipulating physical processes in industrial environments.

If successful, these efforts could result in an OT network going down, a partial loss of view for human operators, lost productivity and revenue, or, in the worst-case scenario, adversary control and disruption to physical processes.

“Cyber campaigns are an ideal way for nation-states to apply pressure on the global stage, because they offer the advantage of plausible deniability plus the rules of engagement are undefined,” Phil Neray, vice president of industrial cybersecurity at CyberX, said via email. “This NSA/CISA advisory is particularly interesting because it appears to be tied to ongoing campaigns targeting industrial control systems, and it explicitly mentions the need for organizations to protect against sophisticated living-off-the-land tactics such as modifying the control logic in process controllers, which is exactly what we saw in the TRITON attack.”

Two partial-loss-of-view incidents have been recorded in the U.S. before: One was a ransomware attack on a pipeline in February that knocked it offline for two days; and the other was an attack on a wind-and-solar power plant last November. Loss of view means that the organization loses the ability to monitor the current status of its physical systems.

Neray said in an interview with Threatpost at the time that “if an attacker wanted to shut down parts of the grid, one of their first steps might be precisely this loss-of-view step, because it would leave utility operators ‘blind’ to subsequent disruptive actions the attackers would take, such as switching relays off to halt the flow of electricity.”

#critical infrastructure #government #hacks #vulnerabilities #advisory #alert #cisa #critical security vulnerability #cve-2020-7491 #cyberattacks #factories #foreign adversaries #ics-cert #industrial control systems #nsa #oil and gas refineries #power plants #schneider #triconex #warning

NSA Urgently Warns on Industrial Cyberattacks, Triconex Critical Bug
meenati biswal

meenati biswal

1582622710

How to Turn Off AMBER Alerts In Android

Before you Turn Off the Alerts know that AMBER Alerts are an incredible tool for the Government to attain out to its Responsible Citizens in instances of Natural Disasters and in case of abduction. Turning them off may cost little treasured lives. But these messages can act as outstanding distractions while you’re riding or attending a vital commercial enterprise meeting.

Amber indicators are supposed to warn mobile smartphone users of approximate kidnappings inside the area. They are part of Wireless Emergency Alerts (WEA), designed via the United States government to alert the public of emergencies such as severe weather situations and presidential announcements concerning emergencies.

As an awful lot as no damage was intended in developing with this approach of indicators, at times we can’t help however sense that the government is pushing the idea down our throats. No one will ever ask in your opinion on whether or no longer you would like to obtain the alerts.

It’s essential to be aware that AMBER indicators are one of a kind from other emergency alerts. For example, in past due 2018 the government examined a new so-called “Presidential Alert,” which can’t become off.

Turning off on iOS

For iOS gadgets, amber indicators and emergency signals are grouped as Government signals.

  • 1st Step
    First and foremost, you may open the settings app. The settings icon is on the home screen. If no longer, swipe your cellphone until you discover it. Tap to open it.
  • 2d Step
    In this step, you will faucet on “Notifications”, to configure the notifications that apps send. Scroll down and on the bottom, you’ll find the section called “Government Alerts”.
  • 3rd Step
    Last but now not least, tap the toggles next to “Amber Alerts” and “Emergency Alerts”. By doing this, you’ll effectively turn off these signals.
    For more update at iOS Course

Turning off on Android

You will notice that there are variations within the Interface of Android telephones. The “Settings” essential to alter your Amber signals are positioned in a unique vicinity for every Android smartphone.

We shall provide tenet to comply with turning off amber indicators in different Android phones.
In Stock Android

  • First Step
    Tap on the Settings app to open it. This app is discovered on the home screen.

  • second Step
    Scroll to the bottom and faucet on Sound. You will need to locate the Cell Broadcasts menu. Tap on “More”, observed by way of “Emergency broadcasts”.

  • third Step
    On the Cell Broadcast settings page, uncheck the box to show off amber alerts. Tap on it another time to disable it.
    Additionally, you can disable indicators for “Severe threats”.

Also, Read
Some Android gadgets have a separate app specifically for Emergency Alerts. It is from this source that you may disable the indicators. Tap on the app to open it.

You then choose “Menu” and head over to “Settings”. From the listing displayed, choose “Receive alerts”. Finally, uncheck the signals that you want to prevent receiving.

Apart from the iPhones and Androids, there are ways of turning off those signals in other telephones as well. We shall briefly guide you through the steps.
Read more info from Android Online Training

#android #androidapp #ios #alert

How to Turn Off  AMBER Alerts In Android