mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
added only notes option
This commit is contained in:
parent
ea59208c38
commit
5a4009d181
2 changed files with 150 additions and 14 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import { mergeAttributes, Node } from '@tiptap/react'
|
||||
import { ReactNodeViewRenderer, NodeViewWrapper } from '@tiptap/react'
|
||||
import { X, Calendar, Video } from 'lucide-react'
|
||||
import { X, Calendar, Video, ChevronDown, Mic } from 'lucide-react'
|
||||
import { blocks } from '@x/shared'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
|
||||
function formatTime(dateStr: string): string {
|
||||
const d = new Date(dateStr)
|
||||
|
|
@ -64,6 +64,57 @@ interface ResolvedEvent {
|
|||
|
||||
const EVENT_BAR_COLOR = '#7ec8c8'
|
||||
|
||||
function JoinMeetingSplitButton({ onJoinAndNotes, onNotesOnly }: {
|
||||
onJoinAndNotes: () => void
|
||||
onNotesOnly: () => void
|
||||
}) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
const handler = (e: MouseEvent) => {
|
||||
if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)
|
||||
}
|
||||
document.addEventListener('mousedown', handler)
|
||||
return () => document.removeEventListener('mousedown', handler)
|
||||
}, [open])
|
||||
|
||||
return (
|
||||
<div className="calendar-block-split-btn" ref={ref}>
|
||||
<button
|
||||
className="calendar-block-split-main"
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => { e.stopPropagation(); onJoinAndNotes() }}
|
||||
>
|
||||
<Video size={13} />
|
||||
Join meeting & take notes
|
||||
</button>
|
||||
<div className="calendar-block-split-chevron-wrap">
|
||||
<button
|
||||
className={`calendar-block-split-chevron ${open ? 'calendar-block-split-chevron-open' : ''}`}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => { e.stopPropagation(); setOpen(!open) }}
|
||||
>
|
||||
<ChevronDown size={12} />
|
||||
</button>
|
||||
{open && (
|
||||
<div className="calendar-block-split-dropdown">
|
||||
<button
|
||||
className="calendar-block-split-option"
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => { e.stopPropagation(); setOpen(false); onNotesOnly() }}
|
||||
>
|
||||
<Mic size={13} />
|
||||
Take notes only
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Shared global to pass calendar event data to App.tsx when joining a meeting.
|
||||
// Set before dispatching the custom event, read by the handler in App.tsx.
|
||||
declare global {
|
||||
|
|
@ -170,10 +221,12 @@ function CalendarBlockView({ node, deleteNode }: { node: { attrs: Record<string,
|
|||
}
|
||||
}
|
||||
|
||||
const handleJoinMeeting = (event: blocks.CalendarEvent & { conferenceLink?: string }, resolvedIdx: number) => {
|
||||
const meetingUrl = event.conferenceLink
|
||||
if (meetingUrl) {
|
||||
window.open(meetingUrl, '_blank')
|
||||
const handleJoinMeeting = (event: blocks.CalendarEvent & { conferenceLink?: string }, resolvedIdx: number, joinCall: boolean) => {
|
||||
if (joinCall) {
|
||||
const meetingUrl = event.conferenceLink
|
||||
if (meetingUrl) {
|
||||
window.open(meetingUrl, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
// Find the original source path from config
|
||||
|
|
@ -249,14 +302,10 @@ function CalendarBlockView({ node, deleteNode }: { node: { attrs: Record<string,
|
|||
{getTimeRange(event)}
|
||||
</div>
|
||||
{showJoinButton && event.conferenceLink && (
|
||||
<button
|
||||
className="calendar-block-join-btn"
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => { e.stopPropagation(); handleJoinMeeting(event, event._idx) }}
|
||||
>
|
||||
<Video size={13} />
|
||||
Join meeting & take notes
|
||||
</button>
|
||||
<JoinMeetingSplitButton
|
||||
onJoinAndNotes={() => handleJoinMeeting(event, event._idx, true)}
|
||||
onNotesOnly={() => handleJoinMeeting(event, event._idx, false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -989,6 +989,93 @@
|
|||
color: color-mix(in srgb, var(--foreground) 45%, transparent);
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-btn {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
margin-top: 4px;
|
||||
border-radius: 5px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-main {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 4px 8px 4px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #7ec8c8;
|
||||
background: color-mix(in srgb, #7ec8c8 12%, transparent);
|
||||
border: 1px solid color-mix(in srgb, #7ec8c8 25%, transparent);
|
||||
border-right: none;
|
||||
border-radius: 5px 0 0 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.12s ease;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-main:hover {
|
||||
background: color-mix(in srgb, #7ec8c8 22%, transparent);
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-chevron-wrap {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-chevron {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px 6px;
|
||||
color: #7ec8c8;
|
||||
background: color-mix(in srgb, #7ec8c8 12%, transparent);
|
||||
border: 1px solid color-mix(in srgb, #7ec8c8 25%, transparent);
|
||||
border-left: 1px solid color-mix(in srgb, #7ec8c8 20%, transparent);
|
||||
border-radius: 0 5px 5px 0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.12s ease;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-chevron:hover {
|
||||
background: color-mix(in srgb, #7ec8c8 22%, transparent);
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-chevron-open {
|
||||
border-radius: 0 5px 0 0;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% - 1px);
|
||||
right: 0;
|
||||
z-index: 50;
|
||||
background: color-mix(in srgb, #7ec8c8 12%, transparent);
|
||||
border: 1px solid color-mix(in srgb, #7ec8c8 25%, transparent);
|
||||
border-top: none;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
white-space: nowrap;
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #7ec8c8;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.12s ease;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-split-option:hover {
|
||||
background: color-mix(in srgb, #7ec8c8 22%, transparent);
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror .calendar-block-join-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue