PageSourceSearch

https://thruline.vercel.app/assets/ImportWhatIRead-kP7qogv2.js

js thruline.vercel.app collected 2026-10-03 07:54:12 UTC 18,604 bytes, 6 lines download raw bytes

1import{m as be,r as A,j as e,an as de,ao as ce,ap as ue,aq as me,ar as he,B as M,a as z,p as K,a0 as pe,s as V,k as we,v as ve,n as _,a5 as Ne,l as ke,bl as Ie,h as Ce,A as Se,C as Ae,K as De}from"./index-CZNtCrEi.js";import{D as $e,S as _e,l as Oe,T as Pe,A as Fe,m as Re,P as Te,n as Ee,o as qe,i as Le,q as Ue,r as Me,j as D,p as W,t as Be,u as Ge,v as ne,h as H,I as E,F as He,H as We,f as ze}from"./HomeWordmarkLink-8M7fcG60.js";import{u as B}from"./ImportFlowContext-LqnaGSwm.js";import{u as xe,a as fe}from"./useImportToolStatus-CKWJWm0R.js";import{U as ge}from"./upload-CsOcfy1G.js";import{I as Ke}from"./ImportFlowHeader-D_RIgBu6.js";import{u as Ve,R as q}from"./useAddedSheetItems-f95gmCaK.js";import{d as Xe,s as Qe}from"./capturePlanClient-CD2xoIOY.js";import{A as Je,a as Ye,b as Ze,c as et,d as tt,e as st,f as at,g as nt}from"./alert-dialog-C58box0Q.js";import{C as rt}from"./clipboard-list-bEM9rcCE.js";import"./importDraft-BMJjKI_t.js";import"./info-WsHy8Z7h.js";import"./useFrontDoorEligibility-CaFaKzcg.js";import"./usePermissions-CXkiixSY.js";import"./useToastWithBot-LGDjoEcf.js";import"./checkbox-BsKjsBu3.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const lt=be("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);let ot=0;const re=()=>`staged-${++ot}`;function it({open:l,onOpenChange:a,readingSummary:m}){const{addFiles:i,addPaste:h}=B(),p=xe(),o=fe(),[s,u]=A.useState([]),[r,d]=A.useState([]),j=()=>{u([]),d([])},I=n=>{n||j(),a(n)},b=()=>{s.length&&i(s.map(n=>n.file));for(const n of r)h(n.text);I(!1)};return e.jsx(de,{open:l,onOpenChange:I,children:e.jsxs(ce,{className:"max-w-2xl gap-0 p-8",children:[e.jsxs(ue,{className:"space-y-2 text-left",children:[e.jsx("p",{className:"font-mono text-2xs uppercase tracking-[0.2em] text-muted-foreground",children:"Add another source"}),e.jsx(me,{className:"font-display text-3xl font-normal",children:"What else should I read?"}),e.jsx(he,{className:"text-base",children:"I'll add it to what I already have and update the review. Nothing you've corrected is lost."})]}),e.jsxs("div",{className:"mt-6 divide-y divide-border/60 border-b border-border/60",children:[e.jsx($e,{status:p.data,variant:"add"}),e.jsx(_e,{status:o.data,variant:"add"}),e.jsx(Oe,{onAdd:n=>u(c=>[...c,...n.map(N=>({id:re(),file:N}))]),children:n=>e.jsx(Pe,{className:Fe,icon:e.jsx(ge,{className:"h-4 w-4"}),name:"Upload files",detail:"One or more files at a time",status:e.jsx("button",{type:"button",onClick:n,className:"inline-flex h-9 items-center rounded-full border border-border px-4 font-medium text-foreground transition-colors hover:bg-muted",children:"Choose files"})})})]}),s.length>0&&e.jsx("div",{className:"mt-2",children:e.jsx(Re,{files:s.map(({id:n,file:c})=>({id:n,name:c.name,size:c.size})),onRemove:n=>u(c=>c.filter(N=>N.id!==n))})}),e.jsx("p",{className:"mb-2 mt-5 text-sm font-semibold text-foreground",children:"Or paste something"}),e.jsx(Te,{pastes:r,onAdd:n=>d(c=>[...c,{id:re(),text:n}]),onRemove:n=>d(c=>c.filter(N=>N.id!==n)),placeholder:r.length?"Paste more, or add a note…":"Paste here…"}),e.jsx("p",{className:"mt-2 text-xs text-muted-foreground",children:"Each paste becomes its own item. Paste as many as you need."}),e.jsxs("div",{className:"mt-6 flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Already reading ",m,"."]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(M,{variant:"outline",className:"!rounded-full",onClick:()=>I(!1),children:"Cancel"}),e.jsx(M,{variant:"primary",className:"!rounded-full",onClick:b,disabled:s.length===0&&r.length===0,children:"Add and update review"})]})]})]})})}const le=V,R=1e3,oe=3e3;function dt(l){const{currentTeam:a}=z(),{currentWorkspace:m}=K(),i=a==null?void 0:a.id,h=m==null?void 0:m.id;return pe({queryKey:["import-drive-files",i,h],enabled:l&&!!(i&&h),staleTime:6e4,queryFn:async()=>{const p=[];for(let s=0;s<oe;s+=R){const{data:u,error:r}=await le.from("artifacts").select("id, title, source_url, updated_at").eq("team_id",i).eq("workspace_id",h).contains("tags",["drive"]).order("updated_at",{ascending:!1}).range(s,s+R-1);if(r)throw r;if(p.push(...u??[]),!u||u.length<R)break}const o=new Set;for(let s=0;s<oe;s+=R){const{data:u,error:r}=await le.from("artifacts").select("id").eq("team_id",i).eq("workspace_id",h).contains("tags",["drive"]).is("content",null).order("id").range(s,s+R-1);if(r)throw r;for(const d of u??[])o.add(d.id);if(!u||u.length<R)break}return p.map(s=>({id:s.id,title:s.title,type:Ee(s.source_url,s.title),updatedAt:s.updated_at,readable:!o.has(s.id)}))}})}function ct(l){const{currentTeam:a}=z(),{currentWorkspace:m}=K(),i=a==null?void 0:a.id,h=m==null?void 0:m.id;return pe({queryKey:["import-slack-captures",i,h],enabled:l&&!!(i&&h),staleTime:6e4,refetchOnWindowFocus:"always",queryFn:async()=>{const{data:p,error:o}=await V.from("uploaded_sources").select("id, file_name, uploaded_at, curation_status").eq("team_id",i).eq("workspace_id",h).eq("file_type","slack").order("uploaded_at",{ascending:!1}).limit(R);if(o)throw o;return(p??[]).filter(s=>
6s.curation_status!=="dismissed").map(s=>({id:s.id,channel:qe(s.file_name)??"slack",label:s.file_name,capturedAt:s.uploaded_at}))}})}const ut=V,mt=25;async function ht(l,a,m,i){const{data:h,error:p}=await ut.from(l).select(`id, ${a}, content`).eq("team_id",i.teamId).eq("workspace_id",i.workspaceId).in("id",m);if(p)throw new Error("Thruline could not read one of the connected sources.");return(h??[]).map(o=>({id:o.id,name:o[a]??"Untitled",content:o.content??""}))}async function ie(l,a,m,i){const h=l==="drive"?"artifacts":"uploaded_sources",p=l==="drive"?"title":"file_name",o=[];let s=0;for(;s<a.length&&m.left>0;){const r=a.slice(s,s+mt);s+=r.length;for(const d of await ht(h,p,r.map(j=>j.id),i))o.push({key:D(l,d.id),kind:l,name:d.name,content:d.content}),m.left-=d.content.length}const u=a.slice(s).map(r=>({key:D(l,r.id),kind:l,name:r.name,content:""}));return{docs:o,unread:u}}function pt({drive:l,slack:a}){const m=we(),{files:i,pastes:h,isIncluded:p,started:o,setStarted:s}=B(),{createProject:u}=ve(),{currentTeam:r}=z(),{currentWorkspace:d}=K(),[j,I]=A.useState(!1),[b,n]=A.useState(null),c=async()=>{const y=[...h.filter(f=>p(D("paste",f.id))).map(f=>({key:D("paste",f.id),kind:"paste",name:W(f.text)||"Pasted note",content:f.text})),...i.filter(f=>f.status==="read"&&p(D("upload",f.id))).map(f=>({key:D("upload",f.id),kind:"upload",name:f.name,content:f.content??""}))],w={left:Be-y.reduce((f,O)=>f+O.content.length,0)};let S={docs:[],unread:[]};if(l.length||a.length){if(!(r!=null&&r.id)||!(d!=null&&d.id))throw new Error("Choose a workspace first.");const f={teamId:r.id,workspaceId:d.id},O=await ie("drive",l,w,f),P=await ie("slack",a,w,f);S={docs:[...O.docs,...P.docs],unread:[...O.unread,...P.unread]}}const v=[...y,...S.docs],T=Ge(v);return{...T,leftOver:[...T.leftOver,...S.unread],docs:[...v,...S.unread]}},N=async y=>{if(!y.text)throw new Error("There is no readable text in what you kept.");let w=o==null?void 0:o.projectId;w?o!=null&&o.capturePlanId&&await Xe(o.capturePlanId).catch(()=>{}):w=(await u({name:Le(y.used)})).id;const S=await Qe({projectId:w,sourceText:y.text,sourceName:Ue(y.used)});s({projectId:w,capturePlanId:S}),m(Me(w))},k=async y=>{I(!0),n(null);try{return await y()}catch(w){return n(w instanceof Error?w.message:"Something went wrong. Try again."),null}finally{I(!1)}};return{busy:j,error:b,gather:()=>k(c),run:y=>k(()=>N(y))}}const C=4,xt={Doc:"Docs",Sheet:"Sheets",Slides:"Slides",PDF:"PDFs",File:"Other files"},x=(l,a,m=`${a}s`)=>`${l.toLocaleString("en-US")} ${l===1?a:m}`;function Ot(){var ee,te,se,ae;const{files:l,pastes:a,isIncluded:m}=B(),i=xe(),h=fe(),p=((ee=i.data)==null?void 0:ee.state)==="connected",o=((te=h.data)==null?void 0:te.state)==="connected",s=dt(p),u=ct(o),[r,d]=A.useState(null),[j,I]=A.useState(!1),[b,n]=A.useState(null),c=A.useMemo(()=>(s.data??[]).filter(t=>t.readable).map(t=>({key:D("drive",t.id),name:t.title,type:t.type,group:xt[t.type],meta:ne(t.updatedAt)})),[s.data]),N=(s.data??[]).filter(t=>!t.readable),k=A.useMemo(()=>(u.data??[]).map(t=>({key:D("slack",t.id),name:t.label,type:`#${t.channel}`,group:`#${t.channel}`,meta:ne(t.capturedAt)})),[u.data]),y=A.useMemo(()=>{const t=new Map;for(const g of k)t.set(g.group,[...t.get(g.group)??[],g]);return Array.from(t.entries())},[k]),w=l.filter(t=>t.status!=="unreadable"),S=l.filter(t=>t.status==="unreadable"),{fileItems:v,pasteItems:T}=Ve({readableOnly:!0}),f=w.reduce((t,g)=>t+g.size,0),O=a.reduce((t,g)=>t+H(g.text),0),P=t=>t.filter(g=>m(g.key)).length,X=[p&&c.length>0,k.length>0,v.length>0,a.length>0].filter(Boolean).length,Q=P(c)+P(k)+P(v)+P(T),J=`${x(Q,"item")} from ${x(X,"source")}`,Y=t=>t.filter(g=>m(g.key)).map(g=>({id:g.key.slice(g.key.indexOf(":")+1),name:g.name})),F=pt({drive:Y(c),slack:Y(k)}),[$,G]=A.useState(null),je=async()=>{const t=await F.gather();t&&(t.leftOver.length?G(t):await F.run(t))},Z=s.isLoading||u.isLoading;return e.jsxs("div",{className:"min-h-screen bg-[hsl(var(--paper))]",children:[e.jsx(Ke,{step:1,backTo:"/start/import",crumbs:["Existing product","What I read"]}),e.jsxs("main",{id:"main-content",className:"mx-auto max-w-6xl px-6 pb-16 pt-8 md:px-12",children:[e.jsxs("div",{className:_("flex flex-wrap items-end justify-between gap-6",E),children:[e.jsxs("div",{className:"max-w-2xl",children:[e.jsx("p",{className:"font-mono text-2xs uppercase tracking-[0.2em] text-ai",children:"What I read"}),e.jsx("h1",{className:"mt-3 font-display text-5xl leading-tight text-foreground",children:"Here's everything I read."}),e.jsx("p",{className:"mt-3 text-lg text-muted-foreground","aria-live":"polite",children:Z?"Gathering what I read…":`${J}. Add anything I'm missing before I tell you what I understood.`})]}),e.jsxs(M,{variant:"outline",size:"lg",className:"!rounded-full",onClick:()=>I(!0),children:[e.jsx(Ne,{className:"mr-2 h-4 w-4"})," Add another source"]})]}),!Z&&X===0?e.jsxs("div",{className:_("mt-10 rounded-xl border border-border/60 bg-card px-6 py-10 text-center",E),children:[e.jsx("p",{className:"text-foreground",children:"Nothing to review yet."}),e.jsxs("p",{className:"mt-1 text-sm text-muted-foreground",children:["Nothing has been added in this tab yet."," ",e.jsx(ke,{to:"/start/import",className:"text-foreground underline underline-offset-2",children:"Bring your product in"}),"."]})]}):e.jsxs("div",{className:"mt-10 grid gap-4 lg:grid-cols-2",children:[p&&e.jsx(L,{index:0,icon:e.jsx(He,{className:"h-4 w-4"}),iconClass:"bg-status-info-subtle text-status-info-fg",title:"Google Drive",subtitle:((se=i.data)==null?void 0:se.state)==="connected"?`${x(i.data.folders,"folder")} · ${x(c.length,"file")}`:"",loading:s.isLoading,rows:c.slice(0,C).map(t=>({key:t.key,name:t.name,meta:t.type})),footer:`Showing ${Math.min(C,c.length)} of ${c.length}`,action:c.length>C?e.jsxs(U,{onClick:()=>d("drive"),children:["Show all ",c.length," files"]}):null,empty:"No readable files synced yet."}),o&&e.jsx(L,{index:1,icon:e.jsx(We,{className:"h-4 w-4"}),iconClass:"bg-status-info-subtle text-status-info-fg",title:"Slack",subtitle:`${x(y.length,"channel")} · ${x(k.length,"capture")}`,loading:u.isLoading,rows:y.slice(0,C).map(([t,g])=>({key:t,name:t,meta:x(g.length,"capture"),keys:g.map(ye=>ye.key)})),footer:`${x(y.length,"channel")} · ${x(k.length,"capture")}`,action:k.length?e.jsx(U,{onClick:()=>
6d("slack"),children:"Show captures"}):null,empty:"No messages captured from these channels yet."}),w.length>0&&e.jsx(L,{index:2,icon:e.jsx(ge,{className:"h-4 w-4"}),iconClass:"bg-status-warning-subtle text-status-warning-fg",title:"Uploaded",subtitle:`${x(w.length,"file")} · ${ze(f)}`,rows:v.slice(0,C).map(t=>({key:t.key,name:t.name,meta:t.meta??""})),footer:v.length>C?`Showing ${C} of ${v.length}`:`All ${v.length} shown`,action:v.length>C?e.jsxs(U,{onClick:()=>d("upload"),children:["Show all ",v.length," files"]}):null}),a.length>0&&e.jsx(L,{index:3,icon:e.jsx(rt,{className:"h-4 w-4"}),iconClass:"bg-status-success-subtle text-status-success-fg",title:"Pasted",subtitle:`${x(a.length,"item")} · ${x(O,"word")}`,rows:a.slice(0,C).map(t=>({key:D("paste",t.id),name:W(t.text)||"Pasted note",meta:x(H(t.text),"word"),onOpen:()=>n(t)})),footer:a.length>C?`Showing ${C} of ${a.length}`:`All ${a.length} shown`,action:a.length>C?e.jsxs(U,{onClick:()=>d("paste"),children:["Show all ",a.length," pastes"]}):e.jsx("span",{className:"text-sm text-muted-foreground",children:"Open any item to read it"})})]}),(S.length>0||N.length>0)&&e.jsxs("div",{className:_("mt-6 flex items-start gap-3 rounded-xl border border-status-warning-border bg-status-warning-subtle px-5 py-4 text-sm",E),style:{animationDelay:"240ms"},role:"status",children:[e.jsx(Ie,{className:"mt-0.5 h-4 w-4 shrink-0 text-status-warning-fg","aria-hidden":"true"}),e.jsxs("div",{className:"space-y-1 text-foreground",children:[S.length>0&&e.jsxs("p",{children:[e.jsxs("span",{className:"font-semibold",children:[x(S.length,"file")," I couldn't read."]})," ",S.map(t=>`${t.name}: ${t.error??"unreadable"}`).join(" · "),". Re-upload them or skip."]}),N.length>0&&e.jsxs("p",{children:[e.jsxs("span",{className:"font-semibold",children:[x(N.length,"Drive file")," with no readable text yet."]})," ","I read Google Docs, Sheets and Slides and plain text; PDFs and other files in Drive are skipped."]})]})]}),e.jsxs("div",{className:_("mt-8 flex flex-wrap items-center justify-between gap-4",E),style:{animationDelay:"300ms"},children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Nothing is created or changed in your tools."}),e.jsxs("div",{className:"flex flex-col items-end gap-2",children:[e.jsx(M,{variant:"primary",size:"lg",className:"!rounded-full",disabled:Q===0||F.busy,onClick:()=>void je(),children:F.busy?e.jsxs(e.Fragment,{children:[e.jsx(Ce,{className:"mr-2 h-4 w-4 animate-spin"})," Getting everything ready…"]}):e.jsxs(e.Fragment,{children:["That's everything. Show me what you understood ",e.jsx(Se,{className:"ml-2 h-4 w-4"})]})}),F.error&&e.jsx("p",{className:"text-sm text-status-error-fg",role:"alert",children:F.error})]})]})]}),e.jsx(q,{open:r==="drive",onOpenChange:t=>d(t?"drive":null),eyebrow:`Google Drive · ${((ae=i.data)==null?void 0:ae.state)==="connected"?x(i.data.folders,"folder"):""}`,title:`All ${c.length} files I read`,noun:"files",items:c}),e.jsx(q,{open:r==="slack",onOpenChange:t=>d(t?"slack":null),eyebrow:`Slack · ${x(y.length,"channel")}`,title:`All ${k.length} captures I read`,noun:"captures",items:k}),e.jsx(q,{open:r==="upload",onOpenChange:t=>d(t?"upload":null),eyebrow:"Uploaded",title:`All ${v.length} files I read`,noun:"files",items:v}),e.jsx(q,{open:r==="paste",onOpenChange:t=>d(t?"paste":null),eyebrow:`Pasted · ${x(O,"word")}`,title:`All ${a.length} pastes I read`,noun:"pastes",items:T}),e.jsx(Je,{open:$!==null,onOpenChange:t=>{t||G(null)},children:e.jsxs(Ye,{children:[e.jsxs(Ze,{children:[e.jsx(et,{children:"Not everything fits in one read."}),e.jsxs(tt,{children:["I can read up to about a million characters at once. I kept pastes and uploads first, then Drive, then Slack.",$?` ${x($.leftOver.length,"item")} won't be read:`:""]})]}),$&&e.jsxs("ul",{className:"max-h-48 list-disc space-y-1 overflow-y-auto pl-5 text-sm text-foreground",children:[$.leftOver.slice(0,8).map(t=>e.jsx("li",{children:t.name},t.key)),$.leftOver.length>8&&e.jsxs("li",{className:"text-muted-foreground",children:["and ",$.leftOver.length-8," more"]})]}),e.jsxs(st,{children:[e.jsx(at,{children:"Go back and trim"}),e.jsx(nt,{onClick:()=>{const t=$;G(null),t&&F.run(t)},children:"Continue without them"})]})]})}),e.jsx(it,{open:j,onOpenChange:I,readingSummary:J}),e.jsx(de,{open:b!==null,onOpenChange:t=>{t||n(null)},children:e.jsxs(ce,{className:"max-w-2xl",children:[e.jsxs(ue,{className:"text-left",children:[e.jsx("p",{className:"font-mono text-2xs uppercase tracking-[0.2em] text-muted-foreground",children:"Pasted"}),e.jsx(me,{className:"font-display text-2xl font-normal",children:b?W(b.text)||"Pasted note":""}),e.jsx(he,{children:b?x(H(b.text),"word"):""})]}),e.jsx("div",{className:"max-h-[60vh] overflow-y-auto whitespace-pre-wrap rounded-lg bg-muted/40 p-4 text-sm leading-6 text-foreground",children:b==null?void 0:b.text})]})})]})}function L({index:l,icon:a,iconClass:m,title:i,subtitle:h,rows:p,footer:o,action:s,loading:u=!1,empty:r}){const{isIncluded:d}=B();return e.jsxs("section",{className:_("flex flex-col rounded-xl border border-border/60 bg-card p-6",E),style:{animationDelay:`${80+l*60}ms`},"aria-label":i,children:[e.jsxs("div",{className:"flex items-center gap-3 border-b border-border/60 pb-4",children:[e.jsx("span",{className:_("flex h-10 w-10 items-center justify-center rounded-lg",m),"aria-hidden":"true",children:a}),e.jsxs("div",{children:[e.jsx("h2",{className:"font-semibold text-foreground",children:i}),e.jsx("p",{className:"text-sm text-muted-foreground",children:u?"Reading…":h})]})]}),e.jsxs("ul",{className:"flex-1 divide-y divide-border/60",children:[!u&&p.length===0&&r&&e.jsx("li",{className:"py-3 text-sm text-muted-foreground",children:r}),p.map(j=>{const I=j.keys??[j.key],b=I.filter(N=>d(N)).length,n=b===I.length?"all":b===0?"none":"some",c=j.onOpen?e.jsx("button",{type:"button",onClick:j.onOpen,className:"min-w-0 flex-1 truncate text-left text-foreground hover:underline",children:j.name}):e.jsx("span",{className:_("min-w-0 flex-1 truncate",n==="none"?"text-muted-foreground line-through":"text-foreground"),children:j.name});return e.jsxs("li",{className:"flex items-center gap-3 py-3 text-sm",children:[e.jsx("span",{className:_("flex h-5 w-5 shrink-0 items-center justify-center rounded-full",n==="none"?"bg-muted text-muted-foreground":"bg-status-success-subtle text-status-success-fg"),"aria-label":n==="all"?"Included":n==="none"?"Left out":"Partly included",children:n==="none"?e.jsx(lt,{className:"h-3 w-3"}):e.jsx(Ae,{className:"h-3 w-3"})}),c,e.jsx("span",{className:"shrink-0 text-muted-foreground",children:j.meta})]},j.key)})]}),e.jsxs("div",{className:"mt-2 flex items-center justify-between border-t border-border/60 pt-4 text-sm text-muted-foreground",children:[e.jsx("span",{children:u?"":o}),s]})]})}function U({onClick:l,children:a}){return e.jsxs("button",{type:"button",onClick:l,className:"inline-flex items-center gap-1 rounded-full bg-muted px-3 py-1.5 text-sm text-foreground transition-colors hover:bg-muted/70",children:[a," ",e.jsx(De,{className:"h-3.5 w-3.5"})]})}
6export{Ot as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.