From 1ee1ed5cf4244e141366808a0943e0f6d283c7e9 Mon Sep 17 00:00:00 2001 From: julianpoyourow Date: Sun, 2 Feb 2025 06:49:40 +0000 Subject: [PATCH 1/4] feat: improve assistant message editing experience --- packages/frontend/src/app/app.scss | 11 ++++++++++ .../assistant/assistant.page.html | 4 ++++ .../assistant/assistant.page.ts | 22 +++++++++++++++++++ packages/frontend/src/assets/i18n/en-us.json | 1 + .../assistant/sendAssistantMessage.ts | 2 +- 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/app/app.scss b/packages/frontend/src/app/app.scss index 1d757ab5a..63975045c 100644 --- a/packages/frontend/src/app/app.scss +++ b/packages/frontend/src/app/app.scss @@ -240,3 +240,14 @@ ion-button.button-outline { --max-width: 300px; --max-height: 300px; } + +.textarea-autogrow-max400-40vh { + .native-wrapper { + max-height: min(400px, 40vh) !important; + + .native-textarea { + max-height: min(400px, 40vh) !important; + overflow-y: auto !important; + } + } +} diff --git a/packages/frontend/src/app/pages/messaging-components/assistant/assistant.page.html b/packages/frontend/src/app/pages/messaging-components/assistant/assistant.page.html index 4a61fd3b2..e06010898 100644 --- a/packages/frontend/src/app/pages/messaging-components/assistant/assistant.page.html +++ b/packages/frontend/src/app/pages/messaging-components/assistant/assistant.page.html @@ -149,6 +149,10 @@

this.maxMessageLength) { + const message = await this.translate + .get("pages.assistant.messageSize") + .toPromise(); + const close = await this.translate.get("generic.okay").toPromise(); + + const toast = await this.toastCtrl.create({ + message, + buttons: [ + { + text: close, + role: "cancel", + }, + ], + }); + await toast.present(); + return; + } + if (this.processing || !pendingMessage) return; this.processing = true; diff --git a/packages/frontend/src/assets/i18n/en-us.json b/packages/frontend/src/assets/i18n/en-us.json index ac3e085af..f98545e93 100644 --- a/packages/frontend/src/assets/i18n/en-us.json +++ b/packages/frontend/src/assets/i18n/en-us.json @@ -483,6 +483,7 @@ "pages.assistant.welcome.4": "This limit only applies to messages sent by you, and not to the AI's responses.", "pages.assistant.welcome.documentation": "Please read the assistant documentation", "pages.assistant.messageLimit": "Maximum messages reached (sorry, it's costly!). Message count resets at 0:00GMT.", + "pages.assistant.messageSize": "Your message is too long. Please send a shorter message.", "pages.messageThread.title": "Conversation with {{name}}", "pages.messageThread.clickToOpen": "Click to open", diff --git a/packages/trpc/src/procedures/assistant/sendAssistantMessage.ts b/packages/trpc/src/procedures/assistant/sendAssistantMessage.ts index 545a03bf3..d9d785926 100644 --- a/packages/trpc/src/procedures/assistant/sendAssistantMessage.ts +++ b/packages/trpc/src/procedures/assistant/sendAssistantMessage.ts @@ -8,7 +8,7 @@ const assistant = new Assistant(); export const sendAssistantMessage = publicProcedure .input( z.object({ - content: z.string().max(500), + content: z.string().max(1500), }), ) .query(async ({ ctx, input }) => { From f5586485a1a64d23c2b22c68eb4ee3e82495931c Mon Sep 17 00:00:00 2001 From: julianpoyourow Date: Sun, 2 Feb 2025 06:52:26 +0000 Subject: [PATCH 2/4] feat: improve offline caching behavior for getsimilarRecipeTitles, and cache purging behavior --- .../serviceWorker/getTrpcResponseForEvent.ts | 22 +++++++++++++++---- .../recipes/registerCreateRecipeRoute.ts | 6 +++-- .../recipes/registerGetSimilarRecipesRoute.ts | 15 +++++++++---- .../recipes/registerUpdateRecipeRoute.ts | 6 +++-- .../recipes/getUniqueRecipeTitle.ts | 6 ++--- .../util/server/src/db/getSimilarRecipes.ts | 2 +- packages/util/server/src/general/index.ts | 1 - packages/util/shared/src/index.ts | 1 + .../src}/stripNumberedRecipeTitle.ts | 0 9 files changed, 41 insertions(+), 18 deletions(-) rename packages/util/{server/src/general => shared/src}/stripNumberedRecipeTitle.ts (100%) diff --git a/packages/frontend/src/app/utils/serviceWorker/getTrpcResponseForEvent.ts b/packages/frontend/src/app/utils/serviceWorker/getTrpcResponseForEvent.ts index e99d8496b..404687573 100644 --- a/packages/frontend/src/app/utils/serviceWorker/getTrpcResponseForEvent.ts +++ b/packages/frontend/src/app/utils/serviceWorker/getTrpcResponseForEvent.ts @@ -2,10 +2,24 @@ import superjson from "superjson"; export const getTrpcResponseBodyForFetchResponse = async ( response: Response, -) => { - const text = await response.clone().text(); +): Promise => { + if (response.status !== 200 && response.status !== 201) { + return undefined; + } - const output = superjson.parse(text); + try { + const json = await response.clone().json(); - return output; + if (!json.result?.data) { + return undefined; + } + + const output = superjson.deserialize(json.result.data); + + return output; + } catch (e) { + console.error(e); + + return undefined; + } }; diff --git a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerCreateRecipeRoute.ts b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerCreateRecipeRoute.ts index 7e4a836ea..a2f7b2158 100644 --- a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerCreateRecipeRoute.ts +++ b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerCreateRecipeRoute.ts @@ -16,8 +16,10 @@ export const registerCreateRecipeRoute = ( ReturnType >(response); - const syncManager = await syncManagerP; - syncManager.syncRecipe(output.id); + if (output) { + const syncManager = await syncManagerP; + syncManager.syncRecipe(output.id); + } return response; }, diff --git a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerGetSimilarRecipesRoute.ts b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerGetSimilarRecipesRoute.ts index 800656f76..e184ed7a3 100644 --- a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerGetSimilarRecipesRoute.ts +++ b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerGetSimilarRecipesRoute.ts @@ -8,6 +8,7 @@ import type { RecipeSummary } from "@recipesage/prisma"; import { getTrpcInputForEvent } from "../../getTrpcInputForEvent"; import { trpcClient as trpc } from "../../../trpcClient"; import { encodeCacheResultForTrpc } from "../../encodeCacheResultForTrpc"; +import { stripNumberedRecipeTitle } from "@recipesage/util/shared"; export const registerGetSimilarRecipesRoute = () => { registerRoute( @@ -40,9 +41,15 @@ export const registerGetSimilarRecipesRoute = () => { ); if (recipe) { - originRecipeTitles.add(recipe.title); - originRecipeIngredients.add(recipe.ingredients); - originRecipeInstructions.add(recipe.instructions); + originRecipeTitles.add(stripNumberedRecipeTitle(recipe.title)); + + if (recipe.ingredients.trim().length) { + originRecipeIngredients.add(recipe.ingredients); + } + + if (recipe.instructions.trim().length) { + originRecipeInstructions.add(recipe.instructions); + } } } @@ -52,7 +59,7 @@ export const registerGetSimilarRecipesRoute = () => { const similarRecipes = recipes.filter((recipe) => { return ( - originRecipeTitles.has(recipe.title) || + originRecipeTitles.has(stripNumberedRecipeTitle(recipe.title)) || originRecipeIngredients.has(recipe.ingredients) || originRecipeInstructions.has(recipe.instructions) ); diff --git a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerUpdateRecipeRoute.ts b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerUpdateRecipeRoute.ts index bd8cca75b..ade945d8f 100644 --- a/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerUpdateRecipeRoute.ts +++ b/packages/frontend/src/app/utils/serviceWorker/routes/recipes/registerUpdateRecipeRoute.ts @@ -16,8 +16,10 @@ export const registerUpdateRecipeRoute = ( ReturnType >(response); - const syncManager = await syncManagerP; - syncManager.syncRecipe(output.id); + if (output) { + const syncManager = await syncManagerP; + syncManager.syncRecipe(output.id); + } return response; }, diff --git a/packages/trpc/src/procedures/recipes/getUniqueRecipeTitle.ts b/packages/trpc/src/procedures/recipes/getUniqueRecipeTitle.ts index c60de020c..a6438b526 100644 --- a/packages/trpc/src/procedures/recipes/getUniqueRecipeTitle.ts +++ b/packages/trpc/src/procedures/recipes/getUniqueRecipeTitle.ts @@ -1,11 +1,9 @@ import { publicProcedure } from "../../trpc"; import { z } from "zod"; import { prisma } from "@recipesage/prisma"; -import { - validateTrpcSession, - stripNumberedRecipeTitle, -} from "@recipesage/util/server/general"; +import { validateTrpcSession } from "@recipesage/util/server/general"; import { recipeSummaryLite } from "@recipesage/prisma"; +import { stripNumberedRecipeTitle } from "@recipesage/util/shared"; /** * An arbitrary upper limit for rename attempts so we don't spin forever diff --git a/packages/util/server/src/db/getSimilarRecipes.ts b/packages/util/server/src/db/getSimilarRecipes.ts index 111ac3480..8bd09fb0e 100644 --- a/packages/util/server/src/db/getSimilarRecipes.ts +++ b/packages/util/server/src/db/getSimilarRecipes.ts @@ -1,5 +1,5 @@ import { prisma, recipeSummaryLite } from "@recipesage/prisma"; -import { stripNumberedRecipeTitle } from "../general/stripNumberedRecipeTitle"; +import { stripNumberedRecipeTitle } from "@recipesage/util/shared"; export const getSimilarRecipes = async ( userId: string, diff --git a/packages/util/server/src/general/index.ts b/packages/util/server/src/general/index.ts index b29c29116..8e9d9268b 100644 --- a/packages/util/server/src/general/index.ts +++ b/packages/util/server/src/general/index.ts @@ -12,7 +12,6 @@ export * from "./email/sendPasswordResetEmail"; export * from "./clip"; export * from "./sortRecipeImages"; export * from "./fileTransformer"; -export * from "./stripNumberedRecipeTitle"; export * from "./config"; export * from "./grip"; export * from "./fetch"; diff --git a/packages/util/shared/src/index.ts b/packages/util/shared/src/index.ts index 2a61cfb18..37c102661 100644 --- a/packages/util/shared/src/index.ts +++ b/packages/util/shared/src/index.ts @@ -8,3 +8,4 @@ export * from "./cleanLabelTitle"; export * from "./preferences"; export * from "./JOB_RESULT_CODES"; export * from "./ImmediateDebouncer"; +export * from "./stripNumberedRecipeTitle"; diff --git a/packages/util/server/src/general/stripNumberedRecipeTitle.ts b/packages/util/shared/src/stripNumberedRecipeTitle.ts similarity index 100% rename from packages/util/server/src/general/stripNumberedRecipeTitle.ts rename to packages/util/shared/src/stripNumberedRecipeTitle.ts From 314eae353654a7b568d312bdebf5fc467a512a9a Mon Sep 17 00:00:00 2001 From: julianpoyourow Date: Sun, 2 Feb 2025 07:23:45 +0000 Subject: [PATCH 3/4] fix: add tsconfig-paths-webpack-plugin --- package-lock.json | 17 +++++++++++++++++ package.json | 1 + packages/frontend/sw-webpack.config.js | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/package-lock.json b/package-lock.json index 180ef6e55..b3c191fee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -162,6 +162,7 @@ "ts-jest": "29.1.2", "ts-loader": "^9.5.2", "ts-node": "~10.9.1", + "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "5.5.4", "webpack": "^5.94.0", "webpack-cli": "^5.1.4", @@ -33859,6 +33860,22 @@ "node": ">=6" } }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/tsconfig-paths/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", diff --git a/package.json b/package.json index c9e0f14df..b273ccfaa 100644 --- a/package.json +++ b/package.json @@ -160,6 +160,7 @@ "ts-jest": "29.1.2", "ts-loader": "^9.5.2", "ts-node": "~10.9.1", + "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "5.5.4", "webpack": "^5.94.0", "webpack-cli": "^5.1.4", diff --git a/packages/frontend/sw-webpack.config.js b/packages/frontend/sw-webpack.config.js index 951ffcfd5..32c449408 100644 --- a/packages/frontend/sw-webpack.config.js +++ b/packages/frontend/sw-webpack.config.js @@ -1,4 +1,5 @@ const path = require("path"); +const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin"); module.exports = { entry: "./src/service-worker.ts", @@ -14,6 +15,11 @@ module.exports = { }, resolve: { extensions: [".ts", ".js"], + plugins: [ + new TsconfigPathsPlugin({ + configFile: path.resolve(__dirname, "tsconfig.json"), + }), + ], }, output: { filename: "service-worker.js", From 18370d51eb65bb5c3350c4830ae8b57a0920bea5 Mon Sep 17 00:00:00 2001 From: julianpoyourow Date: Sun, 2 Feb 2025 07:27:22 +0000 Subject: [PATCH 4/4] feat: increase sync recipe batch size to 200 --- packages/frontend/src/app/utils/SyncManager.ts | 2 +- packages/trpc/src/procedures/recipes/getRecipesByIds.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/app/utils/SyncManager.ts b/packages/frontend/src/app/utils/SyncManager.ts index 4be1f941b..1682c6508 100644 --- a/packages/frontend/src/app/utils/SyncManager.ts +++ b/packages/frontend/src/app/utils/SyncManager.ts @@ -15,7 +15,7 @@ const broadcastChannel = new BroadcastChannel(SW_BROADCAST_CHANNEL_NAME); const ENABLE_VERBOSE_SYNC_LOGGING = false; -const SYNC_BATCH_SIZE = 50; +const SYNC_BATCH_SIZE = 200; /** * How long to wait between syncing each recipe diff --git a/packages/trpc/src/procedures/recipes/getRecipesByIds.ts b/packages/trpc/src/procedures/recipes/getRecipesByIds.ts index 8fca603a0..f4d95ae1b 100644 --- a/packages/trpc/src/procedures/recipes/getRecipesByIds.ts +++ b/packages/trpc/src/procedures/recipes/getRecipesByIds.ts @@ -10,7 +10,7 @@ import { prisma, RecipeSummary, recipeSummary } from "@recipesage/prisma"; export const getRecipesByIds = publicProcedure .input( z.object({ - ids: z.array(z.string()).max(50), + ids: z.array(z.string()).max(200), }), ) .query(async ({ ctx, input }): Promise => {