DEV Community

Cover image for How a Bug Report Led Me to Give Flutter Developers Full Control of Crisp Chat Modals on iOS
Alamin Karno
Alamin Karno

Posted on

How a Bug Report Led Me to Give Flutter Developers Full Control of Crisp Chat Modals on iOS

One of the things I enjoy most about maintaining open-source software is that sometimes the best improvements start with something very small.

A simple bug report.
A curious investigation.
And sometimes… a new feature idea.

This story started exactly like that.


The Bug Report That Started Everything

While reviewing issues for the Flutter Crisp Chat plugin, I noticed a report opened by Nikita Alexeev.

The title immediately caught my attention:

“Taps pass through chat modal to underlying UI on iOS 13+.”

That sounded strange.

A modal should block interactions with the UI behind it. So how could taps reach the Flutter app underneath?

I opened the issue and read the details carefully.

The behavior was simple but frustrating:

  1. Open the Crisp chat on an iPhone
  2. Tap near the top area of the chat
  3. Suddenly the Flutter UI behind it reacts

Buttons could be pressed. Navigation could trigger. All while the chat was still visible.

That’s definitely not the experience anyone wants when they open a support chat.

So I started digging.


Learning Something Interesting About iOS

While reading the issue discussion and the explanation from Nikita Alexeev, I discovered something interesting about iOS.

Starting with iOS 13, Apple changed how modal presentations behave by default.

Before iOS 13, most modals were presented using:

.fullScreen

Which means the modal covers the entire screen. Nothing behind it is visible, and more importantly, nothing behind it can receive touches.

But iOS 13 introduced a new default style:

.pageSheet

This creates the modern sheet-style UI where the modal slides up from the bottom and leaves part of the background visible.

It looks elegant and more native to modern iOS design.

But there was a catch.

In this case, the dimmed background area was still allowing touch events to reach the Flutter UI underneath.

That explained exactly why users were accidentally triggering buttons behind the chat window.

Suddenly the bug made perfect sense.


The Pull Request That Fixed It

Soon after reporting the issue, Nikita Alexeev submitted a pull request with a very straightforward fix.

Instead of relying on the default modal style, he forced the chat view controller to use full screen presentation.

The change looked like this:

let chatVC = ChatViewController()
chatVC.modalPresentationStyle = .fullScreen
viewController.present(chatVC, animated: true)
Enter fullscreen mode Exit fullscreen mode

It was a very small change, but it solved the problem completely.

By forcing .fullScreen, the chat now covered the entire screen again, which meant no touches could leak through to the Flutter UI behind it.

The issue was fixed.

But while reviewing the pull request, a new idea came to my mind.


The Moment the Idea Appeared

Yes, .fullScreen solved the issue.

But iOS actually supports several modal presentation styles.

For example:

  • .fullScreen
  • .pageSheet
  • .formSheet
  • .overFullScreen
  • .overCurrentContext
  • .popover

Different apps use different modal styles depending on their design.

Some apps prefer full screen.

Some prefer sheet-style modals.

Some prefer overlays.

So instead of hardcoding .fullScreen, I thought:

*What if Flutter developers could choose the modal style themselves?
*

That way:

  • The touch-through bug stays fixed
  • Developers get flexibility
  • The plugin becomes more powerful

That’s when the idea shifted from a bug fix to a developer-focused feature.


Turning the Idea into a Feature

To make this possible, I needed to expose the modal presentation style all the way from Flutter to the native iOS implementation.

So I started with the Flutter configuration.


Step 1 — Extending the Flutter Configuration

First, I added a new enum to represent the iOS modal styles.

enum ModalPresentationStyle {
  fullScreen,
  pageSheet,
  formSheet,
  overFullScreen,
  overCurrentContext,
  popover,
}
Enter fullscreen mode Exit fullscreen mode

Then I added it to the CrispConfig class.

class CrispConfig {
  final String websiteID;
  final String? tokenId;
  final ModalPresentationStyle? modalPresentationStyle;

  CrispConfig({
    required this.websiteID,
    this.tokenId,
    this.modalPresentationStyle,
  });
}
Enter fullscreen mode Exit fullscreen mode

Now Flutter developers could specify how the chat modal should appear.


Step 2 — Bridging the Setting to iOS

Next, I needed to convert that Flutter value into a native iOS presentation style.

Inside the Swift plugin code, I mapped the configuration to UIModalPresentationStyle.

switch modalPresentationStyleString {
case "fullScreen":
    modalPresentationStyle = .fullScreen
case "pageSheet":
    modalPresentationStyle = .pageSheet
case "formSheet":
    modalPresentationStyle = .formSheet
case "overFullScreen":
    modalPresentationStyle = .overFullScreen
case "overCurrentContext":
    modalPresentationStyle = .overCurrentContext
case "popover":
    modalPresentationStyle = .popover
default:
    modalPresentationStyle = .fullScreen
}
Enter fullscreen mode Exit fullscreen mode

This ensured a safe default while still allowing flexibility.


Step 3 — Applying the Configuration

Finally, instead of hardcoding .fullScreen, the plugin now uses the configured style.

let chatVC = ChatViewController()
chatVC.modalPresentationStyle = crispConfig.modalPresentationStyle

viewController.present(chatVC, animated: true)
Enter fullscreen mode Exit fullscreen mode

Now Flutter developers have full control over the presentation style.


Making the Feature Easy to Discover

After implementing the improvements, I wanted to make sure developers could easily explore and understand them.

So I also improved the developer experience around the plugin.

I added an interactive demo inside the example app where developers can test different iOS modal styles.

There’s a button called “iOS Modal Style Demo” that opens the chat using different presentation styles so developers can see how each one behaves.

I also updated the documentation to clearly explain:

  • How iOS modal presentation works
  • Why .fullScreen fixes the touch-through issue
  • How to configure the modal style in Flutter

What Developers Gain From This

What started as a small bug report now gives Flutter developers several benefits.

Better User Experience

No more accidental taps on the UI behind the chat.

Flexible Modal Presentation

Developers can choose the modal style that fits their app design.

Platform Awareness

These changes only affect iOS behavior, while Android remains unchanged.


What I Love About Open Source

This experience reminded me why I enjoy maintaining open-source projects.

Sometimes improvements don’t start with big feature ideas.

They start with a simple issue report.

A developer noticing something strange.

A pull request proposing a fix.

And a moment of curiosity that turns a bug fix into something better.

So huge thanks to Nikita Alexeev for reporting the issue and submitting the original fix that inspired this improvement.


Try It Yourself

If you’re using the Flutter Crisp Chat plugin, you can try the new configuration like this:

final config = CrispConfig(
  websiteID: 'YOUR_WEBSITE_ID',
  modalPresentationStyle: ModalPresentationStyle.pageSheet,
  enableNotifications: false,
);
Enter fullscreen mode Exit fullscreen mode

And if you’re curious to see how each modal style behaves, check out the example app in the repository.


Sometimes the best features don’t start with a roadmap.

They start with a bug report…
and a little curiosity.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.