Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed line numbers being selectable in Safari in the lightweight code highlighter. [#1037](https://github.com/sourcebot-dev/sourcebot/pull/1037)
- Fixed GitLab sync deleting repos when the API returns a non-404 error (e.g. 500) during group/user/project fetch. [#1039](https://github.com/sourcebot-dev/sourcebot/pull/1039)
- Fixed React hydration mismatch in `KeyboardShortcutHint` caused by platform detection running at module load time during SSR. [#1041](https://github.com/sourcebot-dev/sourcebot/pull/1041)

### Added
- Added optional copy button to the lightweight code highlighter (`isCopyButtonVisible` prop), shown on hover. [#1037](https://github.com/sourcebot-dev/sourcebot/pull/1037)
Expand Down
14 changes: 8 additions & 6 deletions packages/web/src/app/components/keyboardShortcutHint.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import { cn, IS_MAC } from '@/lib/utils'
import React, { useMemo } from 'react'
import { cn } from '@/lib/utils'
import { useIsMac } from '@/hooks/useIsMac'
import { useMemo } from 'react'

interface KeyboardShortcutHintProps {
shortcut: string
Expand Down Expand Up @@ -81,16 +82,17 @@ function mapKey(key: string, keyMap: Record<string, string>): string {
* Converts react-hotkeys syntax to platform-appropriate keyboard shortcut display.
* Accepts formats like: "mod+b", "alt+shift+f12", "ctrl enter"
*/
function getPlatformShortcut(shortcut: string): string {
function getPlatformShortcut(shortcut: string, isMac: boolean): string {
// Split by + or space to handle both "mod+b" and "⌘ B" formats
const keys = shortcut.split(/[+\s]+/).filter(Boolean);
const keyMap = IS_MAC ? MAC_KEY_MAP : WINDOWS_KEY_MAP;
const keyMap = isMac ? MAC_KEY_MAP : WINDOWS_KEY_MAP;

return keys.map(key => mapKey(key, keyMap)).join(' ');
}

export function KeyboardShortcutHint({ shortcut, label, className }: KeyboardShortcutHintProps) {
const platformShortcut = useMemo(() => getPlatformShortcut(shortcut), [shortcut]);
const isMac = useIsMac();
const platformShortcut = useMemo(() => getPlatformShortcut(shortcut, isMac), [shortcut, isMac]);

return (
<div className={cn("inline-flex items-center", className)} aria-label={label || `Keyboard shortcut: ${platformShortcut}`}>
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/features/chat/components/chatBox/chatBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { Button } from "@/components/ui/button";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { CustomEditor, LanguageModelInfo, MentionElement, RenderElementPropsFor, SearchScope } from "@/features/chat/types";
import { insertMention, slateContentToString } from "@/features/chat/utils";
import { cn, IS_MAC } from "@/lib/utils";
import { cn } from "@/lib/utils";
import { useIsMac } from "@/hooks/useIsMac";
import { computePosition, flip, offset, shift, VirtualElement } from "@floating-ui/react";
import { ArrowUp, Loader2, StopCircleIcon } from "lucide-react";
import { Fragment, KeyboardEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
Expand Down Expand Up @@ -367,6 +368,7 @@ const MentionComponent = ({
}: RenderElementPropsFor<MentionElement>) => {
const selected = useSelected();
const focused = useFocused();
const isMac = useIsMac();

if (data.type === 'file') {
return (
Expand All @@ -384,7 +386,7 @@ const MentionComponent = ({
>
<span contentEditable={false} className="flex flex-row items-center select-none">
{/* @see: https://github.com/ianstormtaylor/slate/issues/3490 */}
{IS_MAC ? (
{isMac ? (
<Fragment>
{children}
<VscodeFileIcon fileName={data.name} className="w-3 h-3 mr-1" />
Expand Down
13 changes: 13 additions & 0 deletions packages/web/src/hooks/useIsMac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client';

import { useState, useEffect } from 'react';

export function useIsMac(): boolean {
const [isMac, setIsMac] = useState(false);

useEffect(() => {
setIsMac(/Mac OS X/.test(navigator.userAgent));
}, []);

return isMac;
}
2 changes: 0 additions & 2 deletions packages/web/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,6 @@ export const getOrgMetadata = (org: Org): OrgMetadata | null => {
return currentMetadata.success ? currentMetadata.data : null;
}

export const IS_MAC = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent);


export const isHttpError = (error: unknown, status: number): boolean => {
return error !== null
Expand Down
Loading