Skip to content

Commit

Permalink
Feat/caption state (#13)
Browse files Browse the repository at this point in the history
* feat: better listener for caption state

introduces swr for polling

* chore: version bump

* fix: close button is not working
  • Loading branch information
pixelass committed Jan 26, 2024
1 parent 00240f1 commit a59380c
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 126 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Captain currently supports English, German, Spanish, French, Hebrew, Italian, Ja


<p align="center">
<a href="https://github.com/blib-la/captain/releases/download/v1.0.0-beta.1/Captain.Setup.1.0.0-beta.1.exe">
<a href="https://github.com/blib-la/captain/releases/download/v1.0.0-beta.2/Captain.Setup.1.0.0-beta.2.exe">
<img src="./docs/download.svg" alt="Download Captain" width="300">
</a>
</p>
Expand Down
7 changes: 6 additions & 1 deletion main/helpers/caption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import path from "node:path";
import fsp from "node:fs/promises";
import { getDirectory, getImageFiles, parseJsonFromString } from "./utils";
import { python } from "./python";
import { OPENAI_API_KEY } from "./constants";
import { CAPTION_RUNNING, OPENAI_API_KEY } from "./constants";

export async function runBlip(directory: string): Promise<any> {
try {
Expand All @@ -21,6 +21,7 @@ export async function runBlip(directory: string): Promise<any> {
if (stderr) {
console.error("Python Error:", stderr);
}
store.set(CAPTION_RUNNING, false);

return stdout?.trim();
} catch (error) {
Expand All @@ -39,6 +40,8 @@ export async function runWd14(directory: string) {
".txt",
"--remove_underscore",
]);
store.set(CAPTION_RUNNING, false);

return stdout?.trim();
} catch (error) {
console.error(error);
Expand Down Expand Up @@ -130,6 +133,8 @@ ${exampleResponse}
console.log(`Description for ${file} written to ${textFilePath}`);
}),
);
store.set(CAPTION_RUNNING, false);
return "done";
} catch (error) {
console.error("Error generating descriptions:", error);
}
Expand Down
5 changes: 3 additions & 2 deletions main/helpers/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Export constants representing the keys for the store.
// These constants are used to avoid hard-coding strings and reduce the risk of typos.
export const OPENAI_API_KEY = "OPENAI_API_KEY";
export const CURRENT_PROJECT_ID = "CURRENT_PROJECT_ID";
export const DIRECTORY = "DIRECTORY";
export const CURRENT_DIRECTORY = "CURRENT_DIRECTORY";
export const EXISTING_PROJECT = "EXISTING_PROJECT";
export const PROJECTS = "PROJECTS";
export const PROJECT = "PROJECT";
Expand All @@ -21,3 +19,6 @@ export const DATASET = "DATASET";
export const DATASETS = "DATASETS";
export const APP = "APP";
export const FOLDER = "FOLDER";

export const FETCH = "FETCH";
export const CAPTION_RUNNING = "CAPTION_RUNNING";
5 changes: 4 additions & 1 deletion main/helpers/create-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
Rectangle,
} from "electron";
import Store from "electron-store";
import { DIRECTORY } from "./constants";
import { CAPTION_RUNNING, DIRECTORY } from "./constants";
import { ensureVisibleOnSomeDisplay, getCurrentPosition } from "./utils";
import { store as userStore } from "./store";

/**
* Creates a new Electron BrowserWindow with specified options.
Expand Down Expand Up @@ -58,6 +59,8 @@ export async function createWindow(
Object.assign(state, getCurrentPosition(win));
}
store.set(key, state);
// Set the caption running flag to false, since all services will be aborted when the app is closed
userStore.set(CAPTION_RUNNING, false);
});

// Setup IPC handler to open directory dialog and return the selected path.
Expand Down
92 changes: 40 additions & 52 deletions main/helpers/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ import {
APP,
BLIP,
CAPTION,
CURRENT_DIRECTORY,
CURRENT_PROJECT_ID,
DATASET,
EXISTING_PROJECT,
FEEDBACK,
FETCH,
FOLDER,
GPT_VISION_OPTIONS,
GPTV,
IMAGE_CACHE,
LOCALE,
OPENAI_API_KEY,
PROJECT,
PROJECTS,
STORE,
Expand All @@ -32,44 +29,59 @@ import { runBlip, runGPTV, runWd14 } from "./caption";
import { Project } from "./types";
import pkg from "../../package.json";

/**
* Sets up IPC event listeners for various channels.
*
* The ipcMain module of Electron is used to set up listeners in the main process,
* which respond to messages sent from renderer processes. Each listener is associated
* with a specific channel, identified by a unique string. When a message is received
* on a channel, the corresponding listener is invoked.
*/
// Handling the 'STORE:set' channel for setting multiple values in the store asynchronously.
ipcMain.handle(
`${STORE}:set`,
async (event, state: Record<string, unknown>) => {
try {
for (const key in state) {
store.set(key, state[key]);
}
} catch (error) {
throw error;
}
},
);

// Listening for 'GPT_VISION_OPTIONS:get' channel. Sends the GPT_VISION_OPTIONS value back to the renderer process.
ipcMain.on(`${GPT_VISION_OPTIONS}:get`, (event) => {
event.sender.send(GPT_VISION_OPTIONS, store.get(GPT_VISION_OPTIONS));
ipcMain.handle(`${LOCALE}:get`, async () => {
return store.get(LOCALE);
});

// Listening for 'OPENAI_API_KEY:get' channel. Sends the OPENAI_API_KEY value back to the renderer process.
ipcMain.on(`${OPENAI_API_KEY}:get`, (event) => {
event.sender.send(OPENAI_API_KEY, store.get(OPENAI_API_KEY));
ipcMain.handle(`${FETCH}:get`, async (event, key: string) => {
return store.get(key);
});
ipcMain.handle(`${FETCH}:delete`, async (event, key: string) => {
return store.delete(key);
});
ipcMain.handle(
`${FETCH}:post`,
async (event, key: string, data: Record<string, unknown>) => {
return store.set(key, data);
},
);

ipcMain.handle(
`${FETCH}:patch`,
async (event, key: string, partialData: Record<string, unknown>) => {
const previousData = (await store.get(key)) as Record<string, unknown>;
return store.set(key, { ...previousData, ...partialData });
},
);

// Listening for 'CURRENT_DIRECTORY:get' channel. Sends the current directory value back to the renderer process.
ipcMain.on(`${CURRENT_DIRECTORY}:get`, (event) => {
event.sender.send(CURRENT_DIRECTORY, store.get(CURRENT_DIRECTORY));
ipcMain.on(`${FOLDER}:open`, (event, path) => {
shell.openPath(path);
});

// Listening for 'CURRENT_PROJECT_ID:get' channel. Sends the current project ID value back to the renderer process.
ipcMain.on(`${CURRENT_PROJECT_ID}:get`, (event) => {
event.sender.send(CURRENT_PROJECT_ID, store.get(CURRENT_PROJECT_ID));
ipcMain.on(`${APP}:close`, () => {
const window = BrowserWindow.getFocusedWindow();
window.close();
});

ipcMain.on(`${APP}:minimize`, () => {
const window = BrowserWindow.getFocusedWindow();
window.minimize();
});

ipcMain.on(`${FOLDER}:open`, (event, path) => {
shell.openPath(path);
});

ipcMain.on(`${APP}:maximize`, () => {
const window = BrowserWindow.getFocusedWindow();
if (window.isMaximized()) {
Expand All @@ -79,30 +91,6 @@ ipcMain.on(`${APP}:maximize`, () => {
}
});

ipcMain.on(`${APP}:close`, () => {
const window = BrowserWindow.getFocusedWindow();
window.close();
});

// Handling the 'STORE:set' channel for setting multiple values in the store asynchronously.
ipcMain.handle(
`${STORE}:set`,
async (event, state: Record<string, unknown>) => {
console.log(state);
try {
for (const key in state) {
store.set(key, state[key]);
}
} catch (error) {
throw error;
}
},
);

ipcMain.handle(`${LOCALE}:get`, async () => {
return store.get(LOCALE);
});

// Handler to fetch project details from the 'projects' directory.
ipcMain.handle(`${PROJECTS}:get`, async (): Promise<Project[]> => {
const projectsDir = getUserData("projects");
Expand Down
2 changes: 1 addition & 1 deletion main/helpers/store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Store from "electron-store";

// Create a new instance of Store. This will be used to save and retrieve data.
export const store = new Store();
export const store = new Store({ name: "com.blibla.captain" });
8 changes: 8 additions & 0 deletions main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
DIRECTORY,
EXISTING_PROJECT,
FEEDBACK,
FETCH,
GPTV,
IMAGE_CACHE,
LOCALE,
Expand All @@ -21,6 +22,13 @@ import { Except } from "type-fest";
const handler = {
store: (data: Record<string, unknown>) =>
ipcRenderer.invoke(`${STORE}:set`, data),
fetch: (
key: string,
{
method = "GET",
data,
}: { method?: "GET" | "POST" | "DELETE" | "PATCH"; data?: unknown } = {},
) => ipcRenderer.invoke(`${FETCH}:${method.toLowerCase()}`, key, data),
sendFeedback: (data: { body: string }) =>
ipcRenderer.invoke(`${FEEDBACK}:send`, data),
saveCaption: (imageData: {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "captain",
"version": "1.0.0-beta.1",
"version": "1.0.0-beta.2",
"private": true,
"description": "The Captain of Captions",
"author": "Gregor Adams <greg@pixelass.com>",
Expand Down Expand Up @@ -77,7 +77,7 @@
"react-hook-form": "^7.49.3",
"react-i18next": "14.0.0",
"remark-gfm": "4.0.0",
"swr": "2.2.4",
"swr": "^2.2.4",
"tslib": "2.6.2",
"type-fest": "4.9.0",
"typescript": "^5.3.3",
Expand Down
1 change: 1 addition & 0 deletions renderer/ions/atoms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ export const imagesAtom = atom<
>([]);
export const directoryAtom = atom("");
export const modelDownloadNoteAtom = atomWithStorage("modelDownloadNote", true);
export const captionRunningAtom = atomWithStorage("captionRunning", false);
1 change: 0 additions & 1 deletion renderer/ions/i18n/redirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export function useRedirect(to?: string) {
const detectedLocale = languageDetector.detect();
const storedLocale = await window.ipc.getLocale();
const appLocale = storedLocale || detectedLocale;
console.log({ detectedLocale, storedLocale, appLocale });
if (to_.startsWith("/" + appLocale) && router.route === "/404") {
// prevent endless loop
await router.replace("/" + appLocale + router.route);
Expand Down
6 changes: 2 additions & 4 deletions renderer/ions/swr/fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import axios from "axios";

export async function fetcher(url: string) {
return axios.get(url).then((response) => response.data);
export async function fetcher(key: string) {
return window.ipc.fetch(key);
}
Empty file added renderer/ions/swr/index.tsx
Empty file.
3 changes: 1 addition & 2 deletions renderer/organisms/language-select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ export function LanguageSelect() {
</StyledValueWrapper>
)}
onChange={async (event, value: string | null) => {
console.log(asPath_, localeRegex);
await window.ipc.store({ [LOCALE]: value });
await window.ipc.fetch(LOCALE, { method: "POST", data: value });
await push(`/${value}${asPath_}`, undefined);
}}
>
Expand Down
3 changes: 1 addition & 2 deletions renderer/organisms/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function SidebarButton({
const { asPath } = useRouter();
const href_ = `/${locale}${href}/`;
const isActive = asPath === href_;
console.log(href_, asPath, disabled);

return (
<Tooltip
placement="right"
Expand Down Expand Up @@ -93,7 +93,6 @@ function SidebarButton({

const WindowControls = () => {
const minimize = () => {
console.log("foo");
window.ipc.send(`${APP}:minimize`);
};

Expand Down

0 comments on commit a59380c

Please sign in to comment.