[desktop] More IPC enhancements and fixes (#1577)
Heading towards a wrap.
This commit is contained in:
commit
eb64cd8367
10 changed files with 73 additions and 37 deletions
|
@ -64,6 +64,7 @@ import {
|
|||
watchFindFiles,
|
||||
watchGet,
|
||||
watchRemove,
|
||||
watchReset,
|
||||
watchUpdateIgnoredFiles,
|
||||
watchUpdateSyncedFiles,
|
||||
} from "./services/watch";
|
||||
|
@ -263,4 +264,6 @@ export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => {
|
|||
ipcMain.handle("watchFindFiles", (_, folderPath: string) =>
|
||||
watchFindFiles(folderPath),
|
||||
);
|
||||
|
||||
ipcMain.handle("watchReset", () => watchReset(watcher));
|
||||
};
|
||||
|
|
|
@ -150,3 +150,7 @@ export const watchFindFiles = async (dirPath: string) => {
|
|||
}
|
||||
return paths;
|
||||
};
|
||||
|
||||
export const watchReset = (watcher: FSWatcher) => {
|
||||
watcher.unwatch(folderWatches().map((watch) => watch.folderPath));
|
||||
};
|
||||
|
|
|
@ -37,26 +37,18 @@ export const registerStreamProtocol = () => {
|
|||
protocol.handle("stream", async (request: Request) => {
|
||||
const url = request.url;
|
||||
// The request URL contains the command to run as the host, and the
|
||||
// pathname of the file as the path. An additional path can be specified
|
||||
// as the URL hash.
|
||||
//
|
||||
// For example,
|
||||
//
|
||||
// stream://write/path/to/file#/path/to/another/file
|
||||
// host[pathname----] [pathname-2---------]
|
||||
//
|
||||
const { host, pathname, hash } = new URL(url);
|
||||
// Convert e.g. "%20" to spaces.
|
||||
const path = decodeURIComponent(pathname);
|
||||
// `hash` begins with a "#", slice that off.
|
||||
const hashPath = decodeURIComponent(hash.slice(1));
|
||||
// pathname of the file(s) as the search params.
|
||||
const { host, searchParams } = new URL(url);
|
||||
switch (host) {
|
||||
case "read":
|
||||
return handleRead(path);
|
||||
return handleRead(ensure(searchParams.get("path")));
|
||||
case "read-zip":
|
||||
return handleReadZip(path, hashPath);
|
||||
return handleReadZip(
|
||||
ensure(searchParams.get("zipPath")),
|
||||
ensure(searchParams.get("entryName")),
|
||||
);
|
||||
case "write":
|
||||
return handleWrite(path, request);
|
||||
return handleWrite(ensure(searchParams.get("path")), request);
|
||||
default:
|
||||
return new Response("", { status: 404 });
|
||||
}
|
||||
|
|
|
@ -208,6 +208,13 @@ const watchOnRemoveDir = (f: (path: string, watch: FolderWatch) => void) => {
|
|||
const watchFindFiles = (folderPath: string) =>
|
||||
ipcRenderer.invoke("watchFindFiles", folderPath);
|
||||
|
||||
const watchReset = async () => {
|
||||
ipcRenderer.removeAllListeners("watchAddFile");
|
||||
ipcRenderer.removeAllListeners("watchRemoveFile");
|
||||
ipcRenderer.removeAllListeners("watchRemoveDir");
|
||||
await ipcRenderer.invoke("watchReset");
|
||||
};
|
||||
|
||||
// - Upload
|
||||
|
||||
const pathForFile = (file: File) => webUtils.getPathForFile(file);
|
||||
|
@ -323,12 +330,13 @@ contextBridge.exposeInMainWorld("electron", {
|
|||
get: watchGet,
|
||||
add: watchAdd,
|
||||
remove: watchRemove,
|
||||
updateSyncedFiles: watchUpdateSyncedFiles,
|
||||
updateIgnoredFiles: watchUpdateIgnoredFiles,
|
||||
onAddFile: watchOnAddFile,
|
||||
onRemoveFile: watchOnRemoveFile,
|
||||
onRemoveDir: watchOnRemoveDir,
|
||||
findFiles: watchFindFiles,
|
||||
updateSyncedFiles: watchUpdateSyncedFiles,
|
||||
updateIgnoredFiles: watchUpdateIgnoredFiles,
|
||||
reset: watchReset,
|
||||
},
|
||||
|
||||
// - Upload
|
||||
|
|
|
@ -111,14 +111,13 @@ function getShrinkRatio(width: number, columns: number) {
|
|||
);
|
||||
}
|
||||
|
||||
const ListContainer = styled(Box)<{
|
||||
columns: number;
|
||||
shrinkRatio: number;
|
||||
groups?: number[];
|
||||
const ListContainer = styled(Box, {
|
||||
shouldForwardProp: (propName) => propName != "gridTemplateColumns",
|
||||
})<{
|
||||
gridTemplateColumns: string;
|
||||
}>`
|
||||
display: grid;
|
||||
grid-template-columns: ${({ columns, shrinkRatio, groups }) =>
|
||||
getTemplateColumns(columns, shrinkRatio, groups)};
|
||||
grid-template-columns: ${(props) => props.gridTemplateColumns};
|
||||
grid-column-gap: ${GAP_BTW_TILES}px;
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
|
@ -235,9 +234,11 @@ const PhotoListRow = React.memo(
|
|||
return (
|
||||
<ListItem style={style}>
|
||||
<ListContainer
|
||||
columns={columns}
|
||||
shrinkRatio={shrinkRatio}
|
||||
groups={timeStampList[index].groups}
|
||||
gridTemplateColumns={getTemplateColumns(
|
||||
columns,
|
||||
shrinkRatio,
|
||||
timeStampList[index].groups,
|
||||
)}
|
||||
>
|
||||
{renderListItem(timeStampList[index], isScrolling)}
|
||||
</ListContainer>
|
||||
|
|
|
@ -23,7 +23,9 @@ export const SearchMobileBox = styled(FluidContainer)`
|
|||
}
|
||||
`;
|
||||
|
||||
export const SearchInputWrapper = styled(CenteredFlex)<{ isOpen: boolean }>`
|
||||
export const SearchInputWrapper = styled(CenteredFlex, {
|
||||
shouldForwardProp: (propName) => propName != "isOpen",
|
||||
})<{ isOpen: boolean }>`
|
||||
background: ${({ theme }) => theme.colors.background.base};
|
||||
max-width: 484px;
|
||||
margin: auto;
|
||||
|
|
|
@ -39,11 +39,12 @@ export const readStream = async (
|
|||
): Promise<{ response: Response; size: number; lastModifiedMs: number }> => {
|
||||
let url: URL;
|
||||
if (typeof pathOrZipItem == "string") {
|
||||
url = new URL(`stream://read${pathOrZipItem}`);
|
||||
const params = new URLSearchParams({ path: pathOrZipItem });
|
||||
url = new URL(`stream://read?${params.toString()}`);
|
||||
} else {
|
||||
const [zipPath, entryName] = pathOrZipItem;
|
||||
url = new URL(`stream://read-zip${zipPath}`);
|
||||
url.hash = entryName;
|
||||
const params = new URLSearchParams({ zipPath, entryName });
|
||||
url = new URL(`stream://read-zip?${params.toString()}`);
|
||||
}
|
||||
|
||||
const req = new Request(url, { method: "GET" });
|
||||
|
@ -89,6 +90,9 @@ export const writeStream = async (
|
|||
path: string,
|
||||
stream: ReadableStream,
|
||||
) => {
|
||||
const params = new URLSearchParams({ path });
|
||||
const url = new URL(`stream://write?${params.toString()}`);
|
||||
|
||||
// TODO(MR): This doesn't currently work.
|
||||
//
|
||||
// Not sure what I'm doing wrong here; I've opened an issue upstream
|
||||
|
@ -119,7 +123,7 @@ export const writeStream = async (
|
|||
});
|
||||
*/
|
||||
|
||||
const req = new Request(`stream://write${path}`, {
|
||||
const req = new Request(url, {
|
||||
method: "POST",
|
||||
body: await new Response(stream).blob(),
|
||||
});
|
||||
|
|
|
@ -40,10 +40,18 @@ export const logoutUser = async () => {
|
|||
} catch (e) {
|
||||
log.error("Ignoring error when clearing files", e);
|
||||
}
|
||||
try {
|
||||
globalThis.electron?.clearStores();
|
||||
} catch (e) {
|
||||
log.error("Ignoring error when clearing electron stores", e);
|
||||
const electron = globalThis.electron;
|
||||
if (electron) {
|
||||
try {
|
||||
await electron.watch.reset();
|
||||
} catch (e) {
|
||||
log.error("Ignoring error when resetting native folder watches", e);
|
||||
}
|
||||
try {
|
||||
await electron.clearStores();
|
||||
} catch (e) {
|
||||
log.error("Ignoring error when clearing native stores", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
eventBus.emit(Events.LOGOUT);
|
||||
|
|
|
@ -462,6 +462,17 @@ export interface Electron {
|
|||
* The returned paths are guaranteed to use POSIX separators ('/').
|
||||
*/
|
||||
findFiles: (folderPath: string) => Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Stop watching all existing folder watches and remove any callbacks.
|
||||
*
|
||||
* This function is meant to be called when the user logs out. It stops
|
||||
* all existing folder watches and forgets about any "on*" callback
|
||||
* functions that have been registered.
|
||||
*
|
||||
* The persisted state itself gets cleared via {@link clearStores}.
|
||||
*/
|
||||
reset: () => Promise<void>;
|
||||
};
|
||||
|
||||
// - Upload
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { styled } from "@mui/material";
|
||||
import { FlexWrapper } from "../../components/Container";
|
||||
const NavbarBase = styled(FlexWrapper)<{ isMobile: boolean }>`
|
||||
|
||||
const NavbarBase = styled(FlexWrapper, {
|
||||
shouldForwardProp: (propName) => propName != "isMobile",
|
||||
})<{ isMobile: boolean }>`
|
||||
min-height: 64px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue