Skip to content

Commit

Permalink
Up retry limit when doing file ops, move to a maintained toast component
Browse files Browse the repository at this point in the history
  • Loading branch information
hatton committed Jun 8, 2024
1 parent 5d24333 commit 3189cdd
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 211 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@
"assert": "^1.4.1",
"axios": "^0.21.1",
"axios-hooks": "^2.2.0",
"butter-toast": "^3.3.5",
"camelcase": "^5.0.0",
"change-case": "^4.1.1",
"commonmark": "^0.28.1",
Expand Down Expand Up @@ -233,6 +232,7 @@
"react-table": "^7.7.0",
"react-table-6": "^6.11.0",
"react-tabs": "^3.0.0",
"react-toastify": "9.1.3",
"react-tooltip-lite": "^1.10.0",
"remark-gfm": "^1.0.0",
"sanitize-filename": "^1.6.1",
Expand Down
286 changes: 104 additions & 182 deletions src/components/Notify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,60 @@ import { css } from "@emotion/react";
import { showInExplorer } from "../other/crossPlatformUtilities";
//import { store } from "react-notifications-component";
import * as React from "react";
import ButterToast, { Cinnamon, POS_BOTTOM, POS_RIGHT } from "butter-toast";
import userSettings from "../other/UserSettings";
import { sentryException } from "../other/errorHandling";
import { t } from "@lingui/macro";
import * as remote from "@electron/remote";
const electron = require("electron");

import { Theme, ToastOptions, toast } from "react-toastify";
export const kred = "#E53935";
const activeToasts: string[] = [];
const autoCloseTicks = 60 * 1000;
export function NotifyError(message: string, details?: string) {
const key = message + details;

// don't show a message again if it's still showing
if (activeToasts.indexOf(key) < 0) {
activeToasts.push(key);
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
ButterToast.raise({
content: (
// expand to fit the insides
<Cinnamon.Crunch
title={t`Error`}
content={
<React.Fragment>
<div>{message}</div>
<div
css={css`
font-size: 8pt;
margin-top: 1em;
overflow-wrap: anywhere;
* {
overflow-wrap: anywhere;
}
`}
>
{details}
</div>
</React.Fragment>
}
scheme={Cinnamon.Crunch.SCHEME_RED}
/>
),
onclick: () => {
try {
const index = activeToasts.indexOf(message);
if (index > -1) activeToasts.splice(index, 1);
} catch (err) {
//swallow
}
},
timeout: autoCloseTicks
}),
0
);
// we don't have a callback from butter-toast, but we know when we told it to hide.
const errorToastProps: ToastOptions = {
type: "error",
theme: "colored" as Theme,
autoClose: 10000
};

window.setTimeout(() => {
try {
const index = activeToasts.indexOf(key);
if (index > -1) activeToasts.splice(index, 1);
} catch (err) {
console.error(err);
}
}, autoCloseTicks);
}
function notify(
message: string,
details?: string | React.ReactNode,
options?: ToastOptions
) {
// the delay helps with messages that we wouldn't see on startup becuase the react window isn't ready for it
window.setTimeout(() => {
const key = message + details;
// don't show a message again if it's still showing
if (activeToasts.indexOf(key) < 0) {
activeToasts.push(key);
toast(
<React.Fragment>
<div>{message}</div>
<div
css={css`
font-size: 8pt;
margin-top: 1em;
overflow-wrap: anywhere;
* {
overflow-wrap: anywhere;
}
`}
>
{details}
</div>
</React.Fragment>,
{
...options,
onClose: () => {
activeToasts.splice(activeToasts.indexOf(key), 1);
}
}
);
}
}, 0);
}
export function NotifyError(message: string, details?: string) {
notify(message, details, errorToastProps);
}
export function getCannotRenameFileMsg() {
return t`lameta was not able to rename that file.`;
Expand Down Expand Up @@ -147,37 +135,27 @@ export function NotifyFileAccessProblem(message: string, err: any) {
https://github.com/onset/lameta/issues.`}
</div>
);
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
ButterToast.raise({
content: (
<Cinnamon.Crunch
title={t`Error`}
css={css``}
content={
<div>
<p>{message}</p>

{/* Enhance: can we get this html into the localization system somehow? For now I think the benefit of the structure outweigh the English-only nature. */}
{tips}
<div
css={css`
font-size: 8pt;
margin-top: 1em;
`}
>
{err && <div>{err.toString()}</div>}
</div>
</div>
}
scheme={Cinnamon.Crunch.SCHEME_RED}
/>
),
timeout: 60 * 1000
}),
0
);
notify(message, err.toString(), errorToastProps);
// toast.error(
// <div>
// <p>{message}</p>

// {/* Enhance: can we get this html into the localization system somehow? For now I think the benefit of the structure outweigh the English-only nature. */}
// {tips}
// <div
// css={css`
// font-size: 8pt;
// margin-top: 1em;
// `}
// >
// {err && <div>{err.toString()}</div>}
// </div>
// </div>,
// {
// ...errorToastProps
// }
// );
}

export function NotifyException(
Expand All @@ -189,85 +167,34 @@ export function NotifyException(
NotifyError(message ? message : errWas, details ?? "" + errWas);
sentryException(err);
}
export function NotifyNoBigDeal(message: string, onClick?: () => void) {
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
ButterToast.raise({
onClick,
content: (
<Cinnamon.Crunch
content={message}
scheme={Cinnamon.Crunch.SCHEME_GREY}
/>
)
}),
0
);
// remove any existing messages of this type
window.setTimeout(() => {
ButterToast.dismissAll((toast) => {
return toast.scheme === Cinnamon.Crunch.SCHEME_GREY;
});
}, 0);
export function NotifyNoBigDeal(message: string) {
notify(message, "", {
type: "warning",
autoClose: 2000,
hideProgressBar: true,
closeButton: false
});
}

export function NotifyWarning(message: string, onClick?: () => void) {
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
ButterToast.raise({
onClick,
content: (
<Cinnamon.Crunch
title={t`Warning`}
content={message}
scheme={Cinnamon.Crunch.SCHEME_ORANGE}
/>
)
}),
0
);
export function NotifyErrorWithClick(message: string, onClick: () => void) {
notify(message, "", { ...errorToastProps, onClick: onClick });
}
export function NotifyWarning(message: string) {
notify(message, "", { type: "warning" });
}
export function NotifySuccess(message: string, onClick?: () => void) {
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
ButterToast.raise({
content: (
<Cinnamon.Crunch
//title={translateMessage(/*i18n*/ { id: "" })}
content={message}
scheme={Cinnamon.Crunch.SCHEME_GREEN}
/>
)
}),
0
);
notify(message, "", {
type: "success",
onClick: onClick,
autoClose: 2000,
hideProgressBar: true
});
}
export function NotifyUpdateAvailable(
open: () => void
//download: DownloadFunction
) {
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(() => {
ButterToast.raise({
content: (
<Cinnamon.Crisp
title={t`Update available`}
//title={translateMessage(/*i18n*/ { id: "" })}
content={
<div>
{/* I would like to dismiss the toast when you click, but the current ButterToast docs don't seem to match what we
actually get if we provide an OnClick to raise. At this time, it does not give a dismiss function as claimed. */}
<a onClick={open}>{t`View Release Notes`}</a>
</div>
}
/>
),
timeout: 10 * 1000
});
}, 0);
notify(t`Update available`, <a onClick={open}>{t`View Release Notes`}</a>);
}

export function NotifyMultipleProjectFiles(
Expand All @@ -276,29 +203,24 @@ export function NotifyMultipleProjectFiles(
name: string,
folder: string
) {
// the delay helps with messages that we wouldn't see on startup becuase the rect window isn't ready for it
window.setTimeout(
() =>
NotifyWarning(
t`There is a problem with the files in the folder for ${displayName}. Click for more information.`,
() => {
electron.ipcRenderer
.invoke("showMessageBox", {
buttons: [t`Cancel`, t`Show me the folder with the problem`],
title: t`Something is wrong here...`,
message: t`There are more than one files of type "${projectType}" in this folder, and there can only be one.`,
detail: t`lameta will now open this folder on your hard disk and then exit. You should open these ${projectType} files in a text editor and decide which one you want, and delete the others. The one you choose should be named ${name}.`
})
.then((response) => {
if (response > 0) {
showInExplorer(folder);
if (!userSettings.DeveloperMode) {
window.setTimeout(() => remote.app.quit(), 1000);
}
}
});
}
),
0
NotifyErrorWithClick(
t`There is a problem with the files in the folder for ${displayName}. Click for more information.`,
() => {
electron.ipcRenderer
.invoke("showMessageBox", {
buttons: [t`Cancel`, t`Show me the folder with the problem`],
title: t`Something is wrong here...`,
message: t`There are more than one files of type "${projectType}" in this folder, and there can only be one.`,
detail: t`lameta will now open this folder on your hard disk and then exit. You should open these ${projectType} files in a text editor and decide which one you want, and delete the others. The one you choose should be named ${name}.`
})
.then((response) => {
if (response > 0) {
showInExplorer(folder);
if (!userSettings.DeveloperMode) {
window.setTimeout(() => remote.app.quit(), 1000);
}
}
});
}
);
}
6 changes: 3 additions & 3 deletions src/components/Workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ class Home extends React.Component<IProps> {
click: () => {
if (this.props.project) {
if (
(this.props.project.getFolderArrayFromType(
folderType
) as any).countOfMarkedFolders() === 0
(
this.props.project.getFolderArrayFromType(folderType) as any
).countOfMarkedFolders() === 0
) {
ShowMessageDialog({
title: ``,
Expand Down
11 changes: 8 additions & 3 deletions src/components/people/person/PersonForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ class PersonForm extends React.Component<IProps> {
validate={(value: string) => this.props.validateFullName(value)}
field={this.props.fields.getTextField("name")}
onBlur={() => {
this.props.person.nameMightHaveChanged();
// ID is s function of the name and the code
this.props.person.IdMightHaveChanged();
if (this.props.person.getNeedRenameOfFolder()) {
// todo: show a dialog that says we're working
setTimeout(() => {
this.props.person.nameMightHaveChanged();
// ID is s function of the name and the code
this.props.person.IdMightHaveChanged();
}, 100);
}
}}
className="full-name left-side"
/>
Expand Down
2 changes: 0 additions & 2 deletions src/containers/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { RenameFileDialog } from "../components/RenameFileDialog/RenameFileDialo
import { I18nProvider } from "@lingui/react";
import { i18n } from "../other/localization";
import RegistrationDialog from "../components/registration/RegistrationDialog";
import ButterToast from "butter-toast";
import userSettingsSingleton from "../other/UserSettings";
import { observer } from "mobx-react";
import { ReleasesDialog } from "../components/ReleasesDialog";
Expand Down Expand Up @@ -42,7 +41,6 @@ export const App: React.FunctionComponent = observer(() => {
<I18nProvider i18n={i18n}>
<ThemeProvider theme={theme}>
<HomePage />
<ButterToast className={"notificationTray"} />
<ConfirmDeleteDialog />
<LanguagePickerDialog />
<RenameFileDialog />
Expand Down
Loading

0 comments on commit 3189cdd

Please sign in to comment.