More lints

This commit is contained in:
Manav Rathi
2025-07-08 14:31:29 +05:30
parent 6221f904e4
commit aa80f86a7a
12 changed files with 90 additions and 65 deletions

View File

@@ -11,7 +11,6 @@ export default [
*/
"@typescript-eslint/no-unnecessary-condition": "off",
/** TODO: Disabled as we migrate, try to prune these again */
"@typescript-eslint/no-floating-promises": "off",
"react-hooks/exhaustive-deps": "off",
},
},

View File

@@ -20,6 +20,7 @@ import { loadCast } from "ente-new/photos/utils/chromecast-sender";
import { t } from "i18next";
import React, { useCallback, useEffect, useState } from "react";
import { Trans } from "react-i18next";
import { z } from "zod/v4";
type AlbumCastDialogProps = ModalVisibilityProps & {
/** The collection that we want to cast. */
@@ -114,7 +115,7 @@ export const AlbumCastDialogContents: React.FC<AlbumCastDialogProps> = ({
useEffect(() => {
if (view == "auto") {
loadCast().then(async (cast) => {
void loadCast().then(async (cast) => {
const instance = cast.framework.CastContext.getInstance();
try {
await instance.requestSession();
@@ -127,29 +128,24 @@ export const AlbumCastDialogContents: React.FC<AlbumCastDialogProps> = ({
session.addMessageListener(
"urn:x-cast:pair-request",
(_, message) => {
const data = message;
// TODO:
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const obj = JSON.parse(data);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
const code = obj.code;
const { code } = CastPairRequest.parse(
JSON.parse(message),
);
if (code) {
publishCastPayload(`${code}`, collection)
.then(() => {
setView("choose");
onClose();
})
.catch((e: unknown) => {
log.error("Error casting to TV", e);
setView("auto-cast-error");
});
}
void publishCastPayload(code, collection)
.then(() => {
setView("choose");
onClose();
})
.catch((e: unknown) => {
log.error("Error casting to TV", e);
setView("auto-cast-error");
});
},
);
const collectionID = collection.id;
session
void session
.sendMessage("urn:x-cast:pair-request", { collectionID })
.then(() => {
log.debug(() => "urn:x-cast:pair-request sent");
@@ -252,3 +248,8 @@ export const AlbumCastDialogContents: React.FC<AlbumCastDialogProps> = ({
</>
);
};
/**
* Zod schema for the "x-cast:pair-request" payload sent by the cast app.
*/
const CastPairRequest = z.object({ code: z.string() });

View File

@@ -627,7 +627,19 @@ const AddParticipantForm: React.FC<AddParticipantFormProps> = ({
});
const resetExistingSelection = () =>
formik.setFieldValue("selectedEmails", []);
void formik.setFieldValue("selectedEmails", []);
const createToggleEmail = (email: string) => {
return () => {
const emails = formik.values.selectedEmails;
void formik.setFieldValue(
"selectedEmails",
emails.includes(email)
? emails.filter((e) => e != email)
: emails.concat(email),
);
};
};
return (
<form onSubmit={formik.handleSubmit}>
@@ -661,18 +673,7 @@ const AddParticipantForm: React.FC<AddParticipantFormProps> = ({
<React.Fragment key={email}>
<RowButton
fontWeight="regular"
onClick={() => {
const emails =
formik.values.selectedEmails;
formik.setFieldValue(
"selectedEmails",
emails.includes(email)
? emails.filter(
(e) => e != email,
)
: emails.concat(email),
);
}}
onClick={createToggleEmail(email)}
label={email}
startIcon={
<Avatar
@@ -761,11 +762,11 @@ const ManageEmailShare: React.FC<ManageEmailShareProps> = ({
const selectAndManageParticipant = useCallback(
(email: string) => {
setSelectedParticipant(
collection.sharees.find((sharee) => sharee.email === email),
collection.sharees.find((sharee) => sharee.email == email),
);
showManageParticipant();
},
[showManageParticipant],
[collection, showManageParticipant],
);
const handleRootClose = () => {
@@ -1120,16 +1121,17 @@ const PublicShare: React.FC<PublicShareProps> = ({
useEffect(() => {
if (publicURL?.url) {
appendCollectionKeyToShareURL(publicURL.url, collection.key).then(
(url) => setResolvedURL(url),
);
void appendCollectionKeyToShareURL(
publicURL.url,
collection.key,
).then((url) => setResolvedURL(url));
} else {
setResolvedURL(undefined);
}
}, [publicURL]);
const handleCopyLink = () => {
if (resolvedURL) navigator.clipboard.writeText(resolvedURL);
if (resolvedURL) void navigator.clipboard.writeText(resolvedURL);
};
return (
@@ -1475,7 +1477,7 @@ const ManagePublicCollect: React.FC<ManagePublicLinkSettingProps> = ({
onUpdate,
}) => {
const handleFileDownloadSetting = () => {
onUpdate({ enableCollect: !publicURL.enableCollect });
void onUpdate({ enableCollect: !publicURL.enableCollect });
};
return (
@@ -1666,7 +1668,9 @@ const ManageDownloadAccess: React.FC<ManagePublicLinkSettingProps> = ({
},
});
} else {
onUpdate({ enableDownload: true });
// TODO: Various calls to onUpdate return promises. The UI should
// handle the in-progress states where needed.
void onUpdate({ enableDownload: true });
}
};

View File

@@ -75,7 +75,7 @@ export const DownloadStatusNotifications: React.FC<
const createOnClick = (group: SaveGroup) => () => {
const electron = globalThis.electron;
if (electron && group.downloadDirPath) {
electron.openDirectory(group.downloadDirPath);
void electron.openDirectory(group.downloadDirPath);
} else if (onShowCollectionSummary) {
onShowCollectionSummary(
group.collectionSummaryID,

View File

@@ -167,7 +167,7 @@ export const FileListWithViewer: React.FC<FileListWithViewerProps> = ({
(editedFile: File, collection: Collection, enteFile: EnteFile) => {
uploadManager.prepareForNewUpload();
uploadManager.showUploadProgressDialog();
uploadManager.uploadFile(editedFile, collection, enteFile);
void uploadManager.uploadFile(editedFile, collection, enteFile);
},
[],
);

View File

@@ -265,6 +265,10 @@ const UserDetailsSection: React.FC<UserDetailsSectionProps> = ({
isSubscriptionStripe(userDetails.subscription) &&
isSubscriptionPastDue(userDetails.subscription)
) {
// TODO: This makes an API request, so the UI should indicate
// the await.
//
// eslint-disable-next-line @typescript-eslint/no-floating-promises
redirectToCustomerPortal();
} else {
onShowPlanSelector();
@@ -337,6 +341,7 @@ const SubscriptionStatus: React.FC<SubscriptionStatusProps> = ({
isSubscriptionStripe(userDetails.subscription) &&
isSubscriptionPastDue(userDetails.subscription)
) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
redirectToCustomerPortal();
} else {
onShowPlanSelector();
@@ -851,16 +856,17 @@ const LanguageSelector = () => {
const locale = getLocaleInUse();
const updateCurrentLocale = (newLocale: SupportedLocale) => {
setLocaleInUse(newLocale);
// [Note: Changing locale causes a full reload]
//
// A full reload is needed because we use the global `t` instance
// instead of the useTranslation hook.
//
// We also rely on this behaviour by caching various formatters in
// module static variables that not get updated if the i18n.language
// changes unless there is a full reload.
window.location.reload();
void setLocaleInUse(newLocale).then(() => {
// [Note: Changing locale causes a full reload]
//
// A full reload is needed because we use the global `t` instance
// instead of the useTranslation hook.
//
// We also rely on this behaviour by caching various formatters in
// module static variables that not get updated if the i18n.language
// changes unless there is a full reload.
window.location.reload();
});
};
const options = supportedLocales.map((locale) => ({
@@ -1088,11 +1094,14 @@ const Help: React.FC<NestedSidebarDrawerVisibilityProps> = ({
continue: { text: t("view_logs"), action: viewLogs },
});
const viewLogs = () => {
const viewLogs = async () => {
log.info("Viewing logs");
const electron = globalThis.electron;
if (electron) electron.openLogDirectory();
else saveStringAsFile(savedLogs(), `ente-web-logs-${Date.now()}.txt`);
if (electron) {
await electron.openLogDirectory();
} else {
saveStringAsFile(savedLogs(), `ente-web-logs-${Date.now()}.txt`);
}
};
return (

View File

@@ -1,6 +1,7 @@
// TODO: Too many null assertions in this file. The types need reworking.
// TODO: Audit this file
/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-floating-promises */
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import DiscFullIcon from "@mui/icons-material/DiscFull";
import GoogleIcon from "@mui/icons-material/Google";

View File

@@ -53,7 +53,7 @@ export const WatchFolder: React.FC<ModalVisibilityProps> = ({
useModalVisibility();
useEffect(() => {
watcher.getWatches().then((ws) => setWatches(ws));
void watcher.getWatches().then((ws) => setWatches(ws));
}, []);
useEffect(() => {
@@ -87,7 +87,7 @@ export const WatchFolder: React.FC<ModalVisibilityProps> = ({
const selectCollectionMappingAndAddWatch = async (path: string) => {
const filePaths = await ensureElectron().fs.findFiles(path);
if (areAllInSameDirectory(filePaths)) {
addWatch(path, "root");
await addWatch(path, "root");
} else {
setSavedFolderPath(path);
showMappingChoice();
@@ -109,7 +109,7 @@ export const WatchFolder: React.FC<ModalVisibilityProps> = ({
const handleCollectionMappingSelect = (mapping: CollectionMapping) => {
setSavedFolderPath(undefined);
addWatch(savedFolderPath!, mapping);
void addWatch(savedFolderPath!, mapping);
};
return (

View File

@@ -89,8 +89,11 @@ const App: React.FC<AppProps> = ({ Component, pageProps }) => {
// the user is logged in.
const handleOpenEnteURL = (url: string) => {
if (url.startsWith("ente://app")) router.push(url);
else log.info(`Ignoring unhandled open request for URL ${url}`);
if (url.startsWith("ente://app")) {
void router.push(url);
} else {
log.info(`Ignoring unhandled open request for URL ${url}`);
}
};
const showUpdateDialog = (update: AppUpdate) => {

View File

@@ -1,3 +1,6 @@
// TODO: Audit this file (the code here is mostly fine, but needs revisiting
// the file it depends on have been audited and their interfaces fixed).
/* eslint-disable @typescript-eslint/no-floating-promises */
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import FileUploadOutlinedIcon from "@mui/icons-material/FileUploadOutlined";
import MenuIcon from "@mui/icons-material/Menu";

View File

@@ -1,4 +1,5 @@
// TODO: Audit this file (too many null assertions)
// TODO: Audit this file (too many null assertions + other issues)
/* eslint-disable @typescript-eslint/no-floating-promises */
import AddPhotoAlternateOutlinedIcon from "@mui/icons-material/AddPhotoAlternateOutlined";
import CloseIcon from "@mui/icons-material/Close";
import DownloadIcon from "@mui/icons-material/Download";

View File

@@ -96,7 +96,7 @@ class FolderWatcher {
this.upload = upload;
this.onTriggerRemotePull = onTriggerRemotePull;
this.registerListeners();
this.syncWithDisk();
this.triggerSyncWithDisk();
}
/** Return `true` if we are currently using the uploader. */
@@ -126,7 +126,7 @@ class FolderWatcher {
*/
resumePausedSync() {
this.isPaused = false;
this.syncWithDisk();
this.triggerSyncWithDisk();
}
/** Return the list of folders we are watching for changes. */
@@ -152,7 +152,7 @@ class FolderWatcher {
*/
async addWatch(folderPath: string, mapping: CollectionMapping) {
const watches = await ensureElectron().watch.add(folderPath, mapping);
this.syncWithDisk();
this.triggerSyncWithDisk();
return watches;
}
@@ -165,6 +165,10 @@ class FolderWatcher {
return await ensureElectron().watch.remove(folderPath);
}
private triggerSyncWithDisk() {
void this.syncWithDisk();
}
private async syncWithDisk() {
try {
const watches = await this.getWatches();