PageSourceSearch

https://aimaster.me/assets/Support-CAnS-JEb.js

js aimaster.me collected 2026-09-24 13:36:34 UTC 19,644 bytes, 1 lines download raw bytes

1import{q as D,t as ne,K as Q,r as m,s as g,O as U,a as A,j as e,m as f,a1 as k,a6 as we,w as ve,v as be,N as _e,C as J,d as ee,e as se,B as M,f as Ce,Q as Se,T as Me,U as ke,W as Te,X as qe,Y as Ae,Z as De,_ as Re,$ as Ee,b as Be,ax as Pe}from"./index-CQ8f4KGU.js";import{p as Fe,B as ie,e as Le,M as te}from"./MainLayout-BaWsfQr8.js";import{u as Qe,Q as ae,S as Ke,M as ze}from"./QuotedMessage-BXjw-79t.js";import{B as T}from"./badge-E6BnLhnH.js";import{S as p}from"./skeleton-C8A6MLvG.js";import{P as I}from"./plus-mjzV0Hjw.js";import{M as q}from"./message-circle-BRQnHGAt.js";import{C as le}from"./credit-card-BGQviTGO.js";import{C as H}from"./circle-help-B6l0dbeI.js";import{L as oe}from"./lightbulb-Mqg-KpJk.js";import{f as ce}from"./useDirectMessages-C9xPkGdB.js";import{f as O}from"./format-CVBQk5T9.js";import{M as Ie}from"./MobilePageHeader-CfbXmOkf.js";import{S as Oe}from"./scroll-area-CJ3H-gOs.js";import{C as Ue}from"./chevron-left--xyuLSlW.js";import{C as He}from"./circle-check-big-xiVIP0jm.js";import{R as $e}from"./rotate-ccw-CiZJ2rj9.js";import{R as We}from"./reply-DMuZUWIo.js";import{S as Ye}from"./send-BMWC_7As.js";import"./avatar-DrfHels3.js";import"./dropdown-menu-DGW8mc-g.js";import"./chevron-right-DmM1wdAc.js";import"./popover-AfRvg-0E.js";import"./trash-2-DaYaPSWR.js";import"./gift-BROb_PyY.js";import"./coins-I_-a7Nb5.js";import"./ThemeSwitcher-DNC7Fvq_.js";import"./shield-check-C8zRvi9V.js";import"./star-BY6kb47t.js";import"./trackUpgradeIntent-jVDcgnk8.js";import"./useProductionAccess-CQT6cE7A.js";import"./useIsProductionInternal-DOR2u0UO.js";import"./graduation-cap-CtIQY-hy.js";import"./flask-conical-CH2v6Nkj.js";import"./palette-CLdneo8G.js";import"./users-BIKmpK09.js";import"./settings-CMDdG4Vl.js";import"./book-open-BgerGNqI.js";import"./message-square-BH_WQYID.js";import"./convertToSrgb-DX7jUL--.js";import"./file-text-jXLcjbaw.js";import"./paperclip-Dd48q6Hr.js";import"./en-US-DguC7roY.js";import"./endOfMonth-CHlpE8px.js";import"./differenceInCalendarDays-DudmbeMs.js";import"./startOfDay-DaHQlETi.js";import"./useSwipeBack-CwaQ7_Jl.js";import"./index-BdQq_4o_.js";function Ge(){const{user:a}=D();return ne({queryKey:["support-threads",a==null?void 0:a.id],queryFn:async()=>{if(!(a!=null&&a.id))return[];const{data:n,error:r}=await g.from("support_threads").select("*").eq("user_id",a.id).order("last_message_at",{ascending:!1,nullsFirst:!1});if(r)throw r;return n},enabled:!!(a!=null&&a.id)})}function Ve(a){const n=Q();return m.useEffect(()=>{if(!a)return;const r=g.channel(`support-messages-${a}`).on("postgres_changes",{event:"INSERT",schema:"public",table:"support_messages",filter:`thread_id=eq.${a}`},i=>{console.log("New support message received:",i),i.new.sender_type==="admin"&&Fe(),n.invalidateQueries({queryKey:["support-messages",a]}),n.invalidateQueries({queryKey:["unread-support-messages"]})}).subscribe();return()=>{g.removeChannel(r)}},[a,n]),ne({queryKey:["support-messages",a],queryFn:async()=>{if(!a)return[];const{data:r,error:i}=await g.from("support_messages").select("*").eq("thread_id",a).order("created_at",{ascending:!0});if(i)throw i;return r},enabled:!!a})}function Xe(){const a=Q(),{user:n}=D();return U({mutationFn:async({message:r,threadId:i,category:y,attachments:x,replyToMessageId:v})=>{if(!(n!=null&&n.id))throw new Error("Not authenticated");let u=i;if(!u){const{data:d,error:t}=await g.from("support_threads").insert({user_id:n.id,status:"open",last_message_at:new Date().toISOString(),last_message_from:"user",category:y||"question"}).select().single();if(t)throw t;u=d.id}const{data:b,error:h}=await g.from("support_messages").insert({thread_id:u,user_id:n.id,sender_type:"user",message:r,reply_to_message_id:v||null}).select().single();if(h)throw h;if(x&&x.length>0){const{error:d}=await g.from("support_message_attachments").insert(x.map(t=>({message_id:b.id,file_path:t.filePath,file_name:t.fileName,file_type:t.fileType,file_size:t.fileSize})));d&&console.error("Error inserting attachments:",d)}const{error:N}=await g.from("support_threads").update({last_message_at:new Date().toISOString(),last_message_from:"user",status:"open"}).eq("id",u);if(N)throw N;return u},onSuccess:r=>{a.invalidateQueries({queryKey:["support-thread"]}),a.invalidateQueries({queryKey:["support-messages",r]})},onError:r=>{A.error("Failed to send message"),console.error(r)}})}function Ze(){const a=Q(),{user:n}=D();return U({mutationFn:async r=>{if(!(n!=null&&n.id))throw new Error("Not authenticated");const{error:i}=await g.from("support_threads").update({status:"closed"}).eq("id",r).eq("user_id",n.id);if(i)throw i;return r},onSuccess:r=>{a.invalidateQueries({queryKey:["support-threads"]}),a.invalidateQueries({queryKey:["support-thread"]}),A.success("Conversation marked as resolved")},onError:r=>{A.error("Failed to close conversation"),console.error(r)}})}function Je(){const a=Q(),{user:n}=D();return U({mutationFn:async r=>{if(!(n!=null&&n.id))throw new Error("Not authenticated");const{error:i}=await g.from("support_threads").update({status:"open"}).eq("id",r).eq("user_id",n.id);if(i)throw i;return r},onSuccess:r=>{a.invalidateQueries({queryKey:["support-threads"]}),a.invalidateQueries({queryKey:["support-thread"]}),A.success("Conversation reopened")},onError:r=>{A.error("Failed to reopen conversation"),console.error(r)}})}const es={bug:ie,feature:oe,question:H,billing:le};function ss({threads:a,isLoading:n,isCreatingNew:r,selectedThreadId:i,onNewChat:y,onSelectThread:x}){const v=t=>{switch(t){case"bug":return"Bug Report";case"feature":return"Feature Request";case"billing":return"Billing";default:return"Question"}},u=t=>es[t]||H,b=t=>{switch(t){case"open":return e.jsx(T,{variant:"default",className:"text-xs",children:"Open"});case"waiting_user":return e.jsx(T,{variant:"secondary",className:"text-xs",children:"Awaiting"});case"closed":return e.jsx(T,{variant:"outline",className:"text-xs",children:"Closed"});default:return null}},h=t=>t.last_message_from==="admin"&&t.last_message_at&&(!t.user_last_seen_at||new Date(t.last_message_at)>new Date(t.user_last_seen_at)),N=()=>{k.light(),y()},d=t=>{k.light(),x(t)};return n?e.jsx("div",{className:"divide-y divide-border rounded-lg border bg-card",children:[1,2,3].map(t=>e.jsxs("div",{className:"p-4 flex items-center gap-3",children:[e.jsx(p,{className:"w-10 h-10 rounded-full shrink-0"}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx(p,{className:"h-4 w-24"}),e.jsx(p,{className:"h-3 w-16"})]})]},t))}):e.jsxs("div",{className:"divide-y divide-border rounded-lg border bg-card overflow-hidden",children:[e.jsxs("button",{onClick:N,className:f("w-full p-4 flex items-center gap-3 text-left","hover:bg-muted/50 active:bg-muted transition-colors",r&&"bg-primary/5"),children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center shrink-0",children:e.jsx(I,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"font-medium text-sm",children:"New Conversation"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Chat with our team"})]})]}),a.length===0&&!r&&e.jsxs("div",{className:"p-6 text-center text-muted-foreground",children:[e.jsx(q,{className:"w-8 h-8 mx-auto mb-2 opacity-50"}),e.jsx("p",{className:"text-sm",children:"No conversations yet"})]}),a.map(t=>{const c=u(t.category);return e.jsxs("button",{onClick:()=>d(t),className:f("w-full p-4 flex items-center gap-3 text-left","hover:bg-muted/50 active:bg-muted transition-colors",i===t.id&&!r&&"bg-muted"),children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-muted flex items-center justify-center shrink-0",children:e.jsx(c,{className:"w-5 h-5 text-muted-foreground"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-sm truncate",children:v(t.category)}),h(t)&&e.jsx("span",{className:"w-2 h-2 rounded-full bg-primary shrink-0"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.last_message_at?ce(new Date(t.last_message_at),{addSuffix:!0}):O(new Date(t.created_at),"MMM d, yyyy")})]}
1),b(t.status)]},t.id)})]})}const re=[{value:"bug",label:"Report a Bug",icon:ie,description:"Something isn't working correctly"},{value:"feature",label:"Suggest a Feature",icon:oe,description:"Share your ideas with us"},{value:"question",label:"General Question",icon:H,description:"Ask us anything"},{value:"billing",label:"Billing Help",icon:le,description:"Payments, subscriptions, tokens"}],Vs=()=>{var Z;const{user:a,loading:n}=D(),{effectivePlanCode:r,isLoading:i}=we(),y=ve(),[x,v]=be(),[u,b]=m.useState(""),[h,N]=m.useState([]),[d,t]=m.useState(null),[c,_]=m.useState(null),[l,R]=m.useState(!1),[C,E]=m.useState(null),[K,B]=m.useState(!1),$=m.useRef(null),{data:w=[],isLoading:P}=Ge(),{data:F=[],isLoading:de}=Ve(c),L=Xe(),W=Ze(),Y=Je(),me=Le(),{isAdminTyping:ue,startTyping:pe,stopTyping:xe}=Qe(c);m.useEffect(()=>{const s=x.get("category"),j=x.get("new")==="true";s&&j&&(R(!0),E(s),_(null),B(!0),v({},{replace:!0}))},[x,v]),m.useEffect(()=>{const s=x.get("new")==="true";!P&&w.length>0&&!c&&!l&&!s&&_(w[0].id)},[w,P,c,l,x]);const he=()=>{var s;(s=$.current)==null||s.scrollIntoView({behavior:"smooth"})};if(m.useEffect(()=>{he()},[F]),m.useEffect(()=>{c&&me.mutate(c)},[c]),n)return e.jsx(te,{children:e.jsxs("div",{className:"p-6",children:[e.jsx(p,{className:"h-8 w-48 mb-2"}),e.jsx(p,{className:"h-4 w-72 mb-6"}),e.jsx(p,{className:"h-96 w-full"})]})});if(!a)return e.jsx(_e,{to:"/auth",replace:!0});const G=async()=>{if(!u.trim()&&h.length===0||l&&!C)return;const s=h.map(S=>({filePath:S.filePath,fileName:S.fileName,fileType:S.fileType,fileSize:S.fileSize})),j=await L.mutateAsync({message:u.trim()||(h.length>0?`📎 ${h.length} file(s) attached`:""),threadId:l?null:c,category:l?C:void 0,attachments:s.length>0?s:void 0,replyToMessageId:(d==null?void 0:d.id)||null});b(""),N([]),t(null),l&&j&&(_(j),R(!1),E(null))},ge=s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),G())},z=()=>{k.light(),_(null),R(!0),E(null),B(!0)},fe=s=>{k.light(),E(s)},V=s=>{k.light(),_(s.id),R(!1),B(!0)},o=w.find(s=>s.id===c),je=de,ye=!i&&r==="trial",Ne=s=>{switch(s){case"open":return e.jsx(T,{variant:"default",className:"text-xs",children:"Open"});case"waiting_user":return e.jsx(T,{variant:"secondary",className:"text-xs",children:"Awaiting Reply"});case"closed":return e.jsx(T,{variant:"outline",className:"text-xs",children:"Closed"});default:return null}},X=s=>{switch(s){case"bug":return"Bug Report";case"feature":return"Feature Request";case"billing":return"Billing";default:return"Question"}};return e.jsxs(te,{hideBottomTabBar:y&&K,hideFloatingHeader:!0,children:[e.jsx(Ie,{title:"Support",subtitle:"Chat with the team"}),e.jsxs("div",{className:"p-4 md:p-6 max-w-5xl mx-auto",children:[e.jsxs("div",{className:"hidden md:block",children:[e.jsx("h1",{className:"text-xl md:text-2xl font-bold mb-0.5",children:"Support"}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3 md:mb-6",children:"Chat with the AI Master team when you need help."})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4 h-[calc(100vh-180px)] md:h-[calc(100vh-280px)] min-h-[400px] md:min-h-[500px]",children:[y&&!K&&e.jsx(ss,{threads:w,isLoading:P,isCreatingNew:l,selectedThreadId:c,onNewChat:z,onSelectThread:V}),e.jsxs(J,{className:f("md:col-span-1 flex flex-col","hidden md:flex"),children:[e.jsx(ee,{className:"border-b py-3 px-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(se,{className:"text-base",children:"Conversations"}),e.jsxs(M,{size:"sm",variant:"outline",onClick:z,children:[e.jsx(I,{className:"w-4 h-4 mr-1"}),"New"]})]})}),e.jsx(Oe,{className:"flex-1",children:P?e.jsxs("div",{className:"p-4 space-y-3",children:[e.jsx(p,{className:"h-16 w-full"}),e.jsx(p,{className:"h-16 w-full"}),e.jsx(p,{className:"h-16 w-full"})]}):w.length===0&&!l?e.jsxs("div",{className:"p-4 text-center text-muted-foreground text-sm",children:[e.jsx(q,{className:"w-8 h-8 mx-auto mb-2 opacity-50"}),e.jsx("p",{children:"No conversations yet"}),e.jsx(M,{size:"sm",variant:"link",onClick:z,children:"Start a new chat"})]}):e.jsxs("div",{className:"divide-y divide-border",children:[l&&e.jsxs("div",{className:"p-3 bg-primary/5 border-l-2 border-primary",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(I,{className:"w-4 h-4 text-primary"}),e.jsx("span",{className:"font-medium text-sm",children:"New Conversation"})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Start typing to begin"})]}),w.map(s=>e.jsx("button",{onClick:()=>V(s),className:f("w-full p-3 text-left hover:bg-muted/50 transition-colors",c===s.id&&!l&&"bg-muted"),children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("span",{className:"text-sm font-medium truncate",children:X(s.
1category)}),s.last_message_from==="admin"&&s.last_message_at&&(!s.user_last_seen_at||new Date(s.last_message_at)>new Date(s.user_last_seen_at))&&e.jsx("span",{className:"w-2 h-2 rounded-full bg-primary shrink-0"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:s.last_message_at?ce(new Date(s.last_message_at),{addSuffix:!0}):O(new Date(s.created_at),"MMM d, yyyy")})]}),Ne(s.status)]})},s.id))]})})]}),e.jsxs(J,{className:f("md:col-span-2 flex flex-col",!K&&"hidden md:flex"),children:[e.jsx(ee,{className:"border-b py-2 px-3 md:py-3 md:px-4",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(M,{variant:"ghost",size:"icon",className:"md:hidden shrink-0 mt-0.5",onClick:()=>{k.light(),_(null),B(!1)},children:e.jsx(Ue,{className:"w-4 h-4"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs(se,{className:"text-sm md:text-base flex items-center gap-2 truncate",children:[e.jsx(q,{className:"w-4 h-4 shrink-0"}),e.jsx("span",{className:"truncate",children:l?"New Conversation":o?X(o.category):"Select a conversation"})]}),e.jsx(Ce,{className:"text-xs truncate",children:l?C?(Z=re.find(s=>s.value===C))==null?void 0:Z.description:"Choose a category to get started":o?e.jsxs(e.Fragment,{children:["Status: ",e.jsx("span",{className:"capitalize",children:o.status.replace("_"," ")})]}):"Choose a conversation from the list"})]}),o&&o.status!=="closed"&&e.jsxs(Se,{children:[e.jsx(Me,{asChild:!0,children:e.jsxs(M,{variant:"outline",size:"sm",className:"shrink-0 text-xs h-8 px-2 md:px-3",children:[e.jsx(He,{className:"w-3 h-3 md:w-4 md:h-4 md:mr-1"}),e.jsx("span",{className:"hidden md:inline",children:"Mark Resolved"}),e.jsx("span",{className:"md:hidden",children:"Resolve"})]})}),e.jsxs(ke,{children:[e.jsxs(Te,{children:[e.jsx(qe,{children:"Mark this conversation as resolved?"}),e.jsx(Ae,{children:"This will close the conversation and mark it as resolved. You can still view the conversation history and reopen it later if needed."})]}),e.jsxs(De,{children:[e.jsx(Re,{children:"Cancel"}),e.jsx(Ee,{onClick:()=>W.mutate(o.id),disabled:W.isPending,children:"Yes, Mark as Resolved"})]})]})]}),o&&o.status==="closed"&&e.jsxs(M,{variant:"outline",size:"sm",className:"shrink-0",onClick:()=>Y.mutate(o.id),disabled:Y.isPending,children:[e.jsx($e,{className:"w-4 h-4 mr-1"}),"Reopen"]})]})}),e.jsxs(Be,{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[!c&&!l?e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-center text-muted-foreground",children:[e.jsx(q,{className:"w-12 h-12 mb-4 opacity-50"}),e.jsx("p",{children:"Select a conversation"}),e.jsx("p",{className:"text-sm",children:"or start a new one"})]}):l&&!C?e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-4 text-center",children:"What can we help you with?"}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-md mx-auto",children:re.map(s=>e.jsxs("button",{onClick:()=>fe(s.value),className:f("flex flex-col items-center p-4 rounded-lg border border-border","hover:border-primary hover:bg-primary/5 transition-colors text-center"),children:[e.jsx(s.icon,{className:"w-8 h-8 mb-2 text-primary"}),e.jsx("span",{className:"font-medium text-sm",children:s.label}),e.jsx("span",{className:"text-xs text-muted-foreground mt-1",children:s.description})]},s.value))})]}):je&&!l?e.jsxs("div",{className:"space-y-3",children:[e.jsx(p,{className:"h-16 w-3/4"}),e.jsx(p,{className:"h-16 w-2/3 ml-auto"}),e.jsx(p,{className:"h-16 w-3/4"})]}):F.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-center text-muted-foreground",children:[e.jsx(q,{className:"w-12 h-12 mb-4 opacity-50"}),e.jsx("p",{children:"No messages yet."}),e.jsx("p",{className:"text-sm",children:"Send a message to start the conversation."})]}):F.map(s=>{const j=s.reply_to_message_id?F.find(S=>S.id===s.reply_to_message_id):null;return e.jsxs("div",{className:f("flex flex-col max-w-[80%] group",s.sender_type==="user"?"ml-auto items-end":"mr-auto items-start"),children:[e.jsxs("div",{className:f("rounded-lg px-4 py-2",s.sender_type==="user"?"bg-primary text-primary-foreground":"bg-muted"),children:[j&&e.jsx("div",{className:f("mb-2 opacity-80",s.sender_type==="user"?"border-primary-foreground
1/50":""),children:e.jsx(ae,{message:j.message,senderType:j.sender_type,compact:!0})}),e.jsx(Ke,{messageId:s.id,legacyAttachmentUrl:s.attachment_url}),e.jsx("p",{className:"whitespace-pre-wrap",children:s.message})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[e.jsxs("span",{className:"text-xs text-muted-foreground",children:[s.sender_type==="admin"&&"AI Master Support · ",O(new Date(s.created_at),"MMM d, h:mm a")]}),(o==null?void 0:o.status)!=="closed"&&e.jsx("button",{onClick:()=>t(s),className:"opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-foreground",children:e.jsx(We,{className:"w-3 h-3"})})]})]},s.id)}),ue&&e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground text-sm ml-2 mb-2",children:[e.jsxs("div",{className:"flex gap-1",children:[e.jsx("span",{className:"w-2 h-2 bg-muted-foreground/60 rounded-full animate-bounce [animation-delay:0ms]"}),e.jsx("span",{className:"w-2 h-2 bg-muted-foreground/60 rounded-full animate-bounce [animation-delay:150ms]"}),e.jsx("span",{className:"w-2 h-2 bg-muted-foreground/60 rounded-full animate-bounce [animation-delay:300ms]"})]}),e.jsx("span",{children:"Support is typing..."})]}),e.jsx("div",{ref:$})]}),(c&&(o==null?void 0:o.status)!=="closed"||l&&C)&&e.jsxs("div",{className:"p-3 md:p-4 border-t space-y-3 pb-keyboard md:pb-4",children:[ye&&e.jsx("p",{className:"text-sm text-muted-foreground bg-muted/50 rounded-md px-3 py-2",children:"On Trial? Feel free to ask us about upgrading or billing."}),d&&e.jsx("div",{className:"bg-muted/50 rounded-md px-3 py-2",children:e.jsx(ae,{message:d.message,senderType:d.sender_type,onClear:()=>t(null)})}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(Pe,{value:u,onChange:s=>{b(s.target.value),s.target.value.trim()&&pe("user")},onBlur:xe,onKeyDown:ge,placeholder:"Type your message...",className:"resize-none min-h-[100px] md:min-h-[80px] w-full",disabled:L.isPending}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(ze,{attachments:h,onAttachmentsChange:N,disabled:L.isPending}),e.jsxs(M,{onClick:G,disabled:!u.trim()&&h.length===0||L.isPending,className:"gap-2",children:[e.jsx(Ye,{className:"w-4 h-4"}),"Send"]})]})]})]})]})]})]})]})};export{Vs 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.