From e0bfc3d961ac2bc4d8a9b0623e2b6a2e9b67be81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 30 May 2026 17:07:55 +0000 Subject: [PATCH] serve static assets from local public/ instead of static.officer.dev, simplify gmail history 404/410 handling Co-Authored-By: Claude Opus 4.7 (1M context) --- public/site.webmanifest | 2 +- src/apps/landing/App.tsx | 4 ++-- src/apps/landing/DuckAvatar.tsx | 4 ++-- src/apps/landing/index.html | 10 +++++----- .../Screens/Authentication/Layout/Background.tsx | 2 +- .../Authentication/Layout/DuckAvatar/DuckModel.tsx | 4 ++-- .../Screens/Dashboard/Layout/Background.tsx | 2 +- .../Screens/Dashboard/Layout/Header/Header.tsx | 2 +- .../Settings/IntegrationsSettings/BrowserRelay.tsx | 2 +- src/apps/officer-web/index.html | 10 +++++----- src/server.tsx | 13 ++++++++++--- src/servers/queue/handlers/gmail-sync.ts | 9 ++------- src/workspaces/components/Logos/DevSvgLogo.tsx | 2 +- .../components/Logos/PastilhasSvgLogo.tsx | 4 ++-- src/workspaces/emailer/emails/UserInvite.tsx | 2 +- .../emailer/emails/layouts/MainLayout.tsx | 2 +- 16 files changed, 38 insertions(+), 36 deletions(-) diff --git a/public/site.webmanifest b/public/site.webmanifest index 07871fa8..eb36d535 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1 +1 @@ -{"name":"Officer Dev","short_name":"Officer","icons":[{"src":"https://static.officer.dev/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"https://static.officer.dev/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#1F2620","background_color":"#1F2620","display":"standalone"} +{"name":"Officer Dev","short_name":"Officer","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#1F2620","background_color":"#1F2620","display":"standalone"} diff --git a/src/apps/landing/App.tsx b/src/apps/landing/App.tsx index 60a7a7da..3f332613 100644 --- a/src/apps/landing/App.tsx +++ b/src/apps/landing/App.tsx @@ -2,8 +2,8 @@ import { PixelGrid } from '../../workspaces/components/PixelGrid'; import { DuckAvatar } from './DuckAvatar'; import { WaitlistForm } from './WaitlistForm'; -const landscapeBg = 'https://static.officer.dev/landscape1.webp'; -const logoSrc = 'https://static.officer.dev/officer-logo.svg'; +const landscapeBg = '/landscape1.webp'; +const logoSrc = '/officer-logo.svg'; export const App = () => { return ( diff --git a/src/apps/landing/DuckAvatar.tsx b/src/apps/landing/DuckAvatar.tsx index e9ddb3f7..6e27d5dc 100644 --- a/src/apps/landing/DuckAvatar.tsx +++ b/src/apps/landing/DuckAvatar.tsx @@ -3,8 +3,8 @@ import { OrbitControls, useGLTF, useAnimations } from '@react-three/drei'; import { useEffect, useState, useRef } from 'react'; function DuckModel({ onLoaded }: { onLoaded: () => void }) { - const character = useGLTF('https://static.officer.dev/duck3D/Character_output.glb'); - const animations = useGLTF('https://static.officer.dev/duck3D/Meshy_Merged_Animations.glb'); + const character = useGLTF('/duck3D/Character_output.glb'); + const animations = useGLTF('/duck3D/Meshy_Merged_Animations.glb'); const meshRef = useRef(null); const { actions } = useAnimations(animations.animations, meshRef); diff --git a/src/apps/landing/index.html b/src/apps/landing/index.html index effdd9b3..e8a8172d 100644 --- a/src/apps/landing/index.html +++ b/src/apps/landing/index.html @@ -11,7 +11,7 @@ - + @@ -25,10 +25,10 @@ - - - - + + + + diff --git a/src/apps/officer-web/Screens/Authentication/Layout/Background.tsx b/src/apps/officer-web/Screens/Authentication/Layout/Background.tsx index 75e0ca9d..1739122c 100644 --- a/src/apps/officer-web/Screens/Authentication/Layout/Background.tsx +++ b/src/apps/officer-web/Screens/Authentication/Layout/Background.tsx @@ -1,7 +1,7 @@ import { DuckAvatar } from "./DuckAvatar"; import { PixelGrid } from "@/components/PixelGrid"; import { useGlobal } from 'hooks/useGlobal'; -const landscapebg = 'https://static.officer.dev/landscape1.webp'; +const landscapebg = '/landscape1.webp'; export function Background() { const [duckHidden] = useGlobal('DUCK_HIDDEN', false); diff --git a/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DuckModel.tsx b/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DuckModel.tsx index 9cf33945..788c74a5 100644 --- a/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DuckModel.tsx +++ b/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DuckModel.tsx @@ -8,8 +8,8 @@ type DuckModelProps = { }; export function DuckModel({ onUpdate, onAssetsLoaded, currentSection }: DuckModelProps) { - const character = useGLTF('https://static.officer.dev/duck3D/Character_output.glb'); - const animations = useGLTF('https://static.officer.dev/duck3D/Meshy_Merged_Animations.glb'); + const character = useGLTF('/duck3D/Character_output.glb'); + const animations = useGLTF('/duck3D/Meshy_Merged_Animations.glb'); const meshRef = useRef(null); const { actions } = useAnimations(animations.animations, meshRef); diff --git a/src/apps/officer-web/Screens/Dashboard/Layout/Background.tsx b/src/apps/officer-web/Screens/Dashboard/Layout/Background.tsx index e60fd821..687ca8e2 100644 --- a/src/apps/officer-web/Screens/Dashboard/Layout/Background.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Layout/Background.tsx @@ -1,5 +1,5 @@ import { PixelGrid } from "@/components/PixelGrid"; -const landscapebg = 'https://static.officer.dev/landscape1.webp'; +const landscapebg = '/landscape1.webp'; export function Background() { return ( diff --git a/src/apps/officer-web/Screens/Dashboard/Layout/Header/Header.tsx b/src/apps/officer-web/Screens/Dashboard/Layout/Header/Header.tsx index 0f8849cf..871de60c 100644 --- a/src/apps/officer-web/Screens/Dashboard/Layout/Header/Header.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Layout/Header/Header.tsx @@ -32,7 +32,7 @@ export function Header({ dockItems }: HeaderProps) { )} Officer { Download and unzip the extension, then load it in Chrome:

diff --git a/src/apps/officer-web/index.html b/src/apps/officer-web/index.html index 5e135a2d..e1d874ba 100644 --- a/src/apps/officer-web/index.html +++ b/src/apps/officer-web/index.html @@ -11,7 +11,7 @@ - + @@ -25,10 +25,10 @@ - - - - + + + + diff --git a/src/server.tsx b/src/server.tsx index de57cb92..e9ea1862 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -20,6 +20,13 @@ import { toShellUsername } from './servers/data-path'; const { PORT = '5000' } = process.env; +// Build static file routes from public/ +const publicRoutes: Record Response> = {}; +for await (const file of new Bun.Glob('**').scan({ cwd: './public' })) { + const bunFile = Bun.file(`./public/${file}`); + publicRoutes[`/${file}`] = () => new Response(bunFile); +} + type WSData = { userId: number; email: string; @@ -256,14 +263,14 @@ const server = serve({ idleTimeout: 60, maxRequestBodySize: 1024 * 1024 * 1024 * 50, // 50 GB routes: { - '/og-image.jpg': () => new Response(Bun.file('public/og-image.jpg'), { headers: { 'Content-Type': 'image/jpeg' } }), + ...publicRoutes, '/novnc/*': (req) => { const file = Bun.file(`public${new URL(req.url).pathname}`); - return new Response(file, { headers: { 'Content-Type': 'application/javascript' } }); + return new Response(file); }, '/vendor/*': (req) => { const file = Bun.file(`public${new URL(req.url).pathname}`); - return new Response(file, { headers: { 'Content-Type': 'application/javascript' } }); + return new Response(file); }, '/api/dev-server-proxy/*': (req, server) => { if (req.headers.get('upgrade') === 'websocket') return upgradeDevServerWs(req, server); diff --git a/src/servers/queue/handlers/gmail-sync.ts b/src/servers/queue/handlers/gmail-sync.ts index 9938c0d4..139980d3 100644 --- a/src/servers/queue/handlers/gmail-sync.ts +++ b/src/servers/queue/handlers/gmail-sync.ts @@ -142,13 +142,8 @@ async function getHistoryChanges( const res = await gmailApiFetch(accessToken, '/history', params); - if (res.status === 404) { - // No history — nothing new - return { messageIds: [], historyId: latestHistoryId }; - } - - if (res.status === 410) { - // historyId too old — caller should fall back to date-based listing + if (res.status === 404 || res.status === 410) { + // historyId too old or invalid — caller should fall back to date-based listing throw new HistoryExpiredError(); } diff --git a/src/workspaces/components/Logos/DevSvgLogo.tsx b/src/workspaces/components/Logos/DevSvgLogo.tsx index ba74fd07..b9fdf61c 100644 --- a/src/workspaces/components/Logos/DevSvgLogo.tsx +++ b/src/workspaces/components/Logos/DevSvgLogo.tsx @@ -7,7 +7,7 @@ export function OfficerIconLogo({ size = 'xl' }: SvgLogoProps) { return ( Officer Icon diff --git a/src/workspaces/components/Logos/PastilhasSvgLogo.tsx b/src/workspaces/components/Logos/PastilhasSvgLogo.tsx index e8c00044..e9480f94 100644 --- a/src/workspaces/components/Logos/PastilhasSvgLogo.tsx +++ b/src/workspaces/components/Logos/PastilhasSvgLogo.tsx @@ -16,7 +16,7 @@ export function OfficerSvgLogoRegular({ size = 'xl' }: SvgLogoProps) { return ( Officer Logo @@ -28,7 +28,7 @@ export function OfficerSvgLogoSquare({ size = 'xl' }: SvgLogoProps) { return ( Officer Logo diff --git a/src/workspaces/emailer/emails/UserInvite.tsx b/src/workspaces/emailer/emails/UserInvite.tsx index dde700b5..8ef5d6ce 100644 --- a/src/workspaces/emailer/emails/UserInvite.tsx +++ b/src/workspaces/emailer/emails/UserInvite.tsx @@ -15,7 +15,7 @@ const Email = ({ invitedBy, url }: EmailProps) => { officer.dev diff --git a/src/workspaces/emailer/emails/layouts/MainLayout.tsx b/src/workspaces/emailer/emails/layouts/MainLayout.tsx index cf071b30..0d00fe87 100644 --- a/src/workspaces/emailer/emails/layouts/MainLayout.tsx +++ b/src/workspaces/emailer/emails/layouts/MainLayout.tsx @@ -10,7 +10,7 @@ const MainLayout = ({ children }: { children: ReactNode }) => { Officer Logo