Skip to content

Commit bcb1e09

Browse files
committed
fix(extension): preserve capture focus and Sim Link routes
1 parent 4988bb6 commit bcb1e09

7 files changed

Lines changed: 26 additions & 15 deletions

File tree

‎apps/extension/src/background.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ function open(tab: chrome.tabs.Tab, trigger: 'page' | 'selection' | 'keyboard')
5555
active instanceof HTMLElement &&
5656
(active.isContentEditable ||
5757
active.matches('iframe,frame,input,textarea,select') ||
58-
active.localName.includes('-') ||
5958
Boolean(chrome.dom.openOrClosedShadowRoot(active)?.activeElement))
6059
return {
6160
href: location.href,

‎apps/extension/src/extract.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export function extractPageText(
2121
active instanceof HTMLElement &&
2222
(active.isContentEditable ||
2323
active.matches('input,textarea,select') ||
24-
active.localName.includes('-') ||
2524
chrome.dom.openOrClosedShadowRoot(active)?.activeElement)
2625
)
2726
return { error: 'Select text outside an editable or embedded field.' }

‎apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ export function Composer({
203203
history.reset()
204204
editor.clear()
205205
},
206-
() => editorRef.current.getValue() === raw && attachedFilesRef.current === filesAtSend
206+
() => editorRef.current.getValue() === raw && attachedFilesRef.current === filesAtSend,
207+
textareaRef.current
207208
)
208209
}
209210

‎apps/sim/app/sim-links/[organizationId]/[name]/page.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ interface OrganizationLinkPageProps {
1313

1414
/** Bookmarks stay in their exporting organization even after the browser's active team changes. */
1515
export default async function OrganizationLinkPage({ params }: OrganizationLinkPageProps) {
16-
const { organizationId, name } = await params
16+
const { organizationId, name: encodedName } = await params
17+
const name = decodeURIComponent(encodedName)
1718
if (!simLinkNameSchema.safeParse(name).success) notFound()
1819
const routes = organizationRoutes(organizationId)
1920
const session = await getSession()

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,8 @@ const UserInputImpl = forwardRef<UserInputHandle, UserInputProps>(function UserI
574574
clearComposer,
575575
() =>
576576
editorRef.current.getValue() === raw &&
577-
filesRef.current.attachedFiles === currentFiles.attachedFiles
577+
filesRef.current.attachedFiles === currentFiles.attachedFiles,
578+
currentEditor.textareaRef.current
578579
)
579580
}, [chatPlanRequired, workspaceId, onSubmit, clearComposer, acceptSubmission])
580581

‎apps/sim/hooks/use-composer-submission.ts‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,41 @@ interface UseComposerSubmissionProps {
2626

2727
export function useComposerSubmission({ scope, mode }: UseComposerSubmissionProps) {
2828
const active = useRef<PendingComposerSubmission | null>(null)
29-
const focusBeforeSend = useRef<HTMLElement | null>(null)
29+
const focusAfterSend = useRef<HTMLTextAreaElement | null>(null)
3030
const [pending, setPending] = useState(false)
3131

3232
useLayoutEffect(() => {
3333
setPending(false)
3434
return () => {
3535
active.current = null
36-
focusBeforeSend.current = null
36+
focusAfterSend.current = null
3737
}
3838
}, [scope, mode])
3939

4040
useLayoutEffect(() => {
4141
if (pending) return
42-
const previous = focusBeforeSend.current
43-
focusBeforeSend.current = null
44-
if (previous?.isConnected && document.hasFocus() && document.activeElement === document.body) {
45-
previous.focus({ preventScroll: true })
42+
const input = focusAfterSend.current
43+
focusAfterSend.current = null
44+
if (input?.isConnected && document.hasFocus() && document.activeElement === document.body) {
45+
input.focus({ preventScroll: true })
4646
}
4747
}, [pending])
4848

4949
const accept = useCallback(
50-
(submit: () => unknown, clear: () => void, unchanged: () => boolean) => {
50+
(
51+
submit: () => unknown,
52+
clear: () => void,
53+
unchanged: () => boolean,
54+
input: HTMLTextAreaElement | null
55+
) => {
5156
if (active.current) return
5257
const result = submit()
5358
if (!(result instanceof PendingComposerSubmission)) {
5459
if (result !== false) clear()
5560
return
5661
}
5762
active.current = result
58-
focusBeforeSend.current =
59-
document.activeElement instanceof HTMLElement ? document.activeElement : null
63+
focusAfterSend.current = input
6064
setPending(true)
6165
void result.ready
6266
.then((commit) => {

‎apps/sim/proxy.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,14 +233,20 @@ const SUSPICIOUS_UA_PATTERNS = [
233233
] as const
234234

235235
/**
236-
* Handles authentication-based redirects for root paths
236+
* Resolves legacy homepage aliases and authentication-based root redirects.
237237
*/
238238
function handleRootPathRedirects(
239239
request: NextRequest,
240240
hasActiveSession: boolean
241241
): NextResponse | null {
242242
const url = request.nextUrl
243243

244+
if (url.pathname !== '/sim' && url.pathname.toLowerCase() === '/sim') {
245+
const destination = url.clone()
246+
destination.pathname = '/'
247+
return NextResponse.redirect(destination, 308)
248+
}
249+
244250
if (url.pathname !== '/' || url.searchParams.has('home')) {
245251
return null
246252
}

0 commit comments

Comments
 (0)