Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2174: Replace unmaintained react-toast-notifications (and use one style for all toasts) #2836

Merged
merged 18 commits into from
Mar 3, 2022

Conversation

fregante
Copy link
Contributor

@fregante fregante commented Feb 28, 2022

Status: Rrrrrrrrrready

One notify.* API to rule them all. It replaces:

  • addToast
  • showNotification
  • useNotifications

Also standardizes the notify.error => automatically reportError

Currently-supported pages

  • sidebar
  • options
  • editor
  • contentScript

Demo

Notice:

  • the new style of notifications
  • the really-always-on-top z-index that notifications should have
Screen.Recording.3.mov

notify.error("Error updating account alias", {
error,
});
notify.error({ message: "Error updating account alias", error });
Copy link
Contributor Author

@fregante fregante Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API improvement: Either call it with a plain string or provide a regular Notification object.

Pros:

  • no awkward { error } wrap
  • simpler types
  • safer: no unknown as the first parameter of notify.error just to allow notify.error(new Error())

Cons:

  • 8 extra characters 😌 message: if you need to include the error

Copy link
Contributor

@twschiller twschiller Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 extra characters 😌 message: if you need to include the error

I'm not sure we have the budget for the extra storage

message: `Error adding ${name} to Pipedrive`,
type: "error",
});
notify.error(`Error adding ${name} to Pipedrive`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @twschiller suggested in https://github.com/pixiebrix/pixiebrix-app/pull/1252, errors are automatically reported. This was not the case with the previous showNotification implementation so let me know if I should set report: false to some of these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should actually be logger statements and BusinessErrors. Will change these

MENU_INSTALL_ERROR_DEBOUNCE_MS,
{
leading: true,
trailing: false,
}
);
) as typeof notify.error; // `debounce` loses the overloads
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: we might want to use memoize instead since this debounce may lump together unrelated errors.

Copy link
Contributor

@twschiller twschiller Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memoize won't work unless we define a custom equality function (over message). Debounce should be fine here in practice, since having multiple specific errors doesn't help much. This is more about not spamming the end-user with error notifications

{ error, report: true }
);
notify.warning({
message: `Error fetching latest bricks from server: ${getErrorMessage(
Copy link
Contributor Author

@fregante fregante Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"notify.warning" … "Error"

Is it a warning or an error? When should an error be displayed as a warning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nuance is that with a warning, the user still might be OK continuing. But with an error, they would expect to no be able to proceed successfully. I'll change the message to clarify

message:
"You must update the PixieBrix browser extension to activate the deployment",
});
reportEvent("DeploymentRejectVersion");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error notifications almost always need to be reported and sometimes are reported with the exact same user message.

Events on the other hand have zero data overlap with notifications and so far only appear ~8 times in the whole extension, one of which was actually reported twice. Having events as an optional parameter means that its use must always be deliberate and explicit.

Events may also have additional attached data which would further complicate the notifier for little benefit.

For these reasons I dropped the event option from the notifier.

Copy link
Contributor

@twschiller twschiller Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these reasons I dropped the event option from the notifier

Sure, I think this makes sense. We'll give it a try

} else {
const message = `Error handling context menu action: ${getErrorMessage(
error
)}`;
reportError(new Error(message));
void showNotification(target, { message, type: "error" });
reportError(error);
Copy link
Contributor Author

@fregante fregante Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to report the original error here. The stack trace will point to this block anyway, but its origin will be better defined.

Here it's called explicitly because the messaging API does not automatically serialize errors, especially deep inside other objects.

Comment on lines +139 to 142
notify.success(`Removed brick ${getLabel(installable)}`);
reportEvent("ExtensionRemove", {
extensionId: installable.id,
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case reportEvent was called implicitly and explicitly

message:
"Error refreshing service configurations, restart the PixieBrix extension",

error,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notify.warning never reported this error. @twschiller Pick one:

  • Drop line
  • Add report: true
  • Change to report.error

Same thing for the error below, in the same file

const notify = {
/**
* @example notify.error('User message')
* @example notify.error({error: new Error('Error that can be shown to the user')})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This notifyError({error}) only happens a couple of times in the extension. We should probably not show raw errors to the user without adding some context, so I suggest requiring a message as always and only use error for the reporting:

} catch (error) {
	notifyError({
		error,
		message: "Stuff failed because: " + getErrorMessage(error)
	})
}

@fregante fregante marked this pull request as ready for review March 1, 2022 06:43
appearance: "error",
autoDismiss: true,
notify.success("Cleared the log entries for this extension");
} catch (error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error was not reported, now it is.

@twschiller twschiller self-requested a review March 3, 2022 00:30
@twschiller
Copy link
Contributor

twschiller commented Mar 3, 2022

I'm good with this for now. Future considerations:

  1. We may potentially want to re-add as a hook if we want control of showing/hiding based on other application state. For just triggering toasts this PR is cleaner
  2. Instead of having ad-hoc toast message creation (some including error details, some using getHumanDetail, some using getErrorMessage), I think we'll want to standardize to have:
// The message describing the operation that failed
message: string;

// The error detail, which the getHumanDetail will be called on
error: unknown;

// True to report the error to Rollbar (default: true)
reportError?: boolean;

// True to show the error detail to the user (default: true)
showDetails?: boolean;

In this world, the error detail will probably be less prominent (e.g., smaller font size)

@twschiller twschiller added this to the 1.5.6 milestone Mar 3, 2022
@twschiller
Copy link
Contributor

image

@twschiller twschiller merged commit 5f3169e into main Mar 3, 2022
@twschiller twschiller deleted the F/feature/one-love-one-notify branch March 3, 2022 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants