commits list and commit view
156 unmodified linesExpand all15715815916016116116216316416542 unmodified lines20820921021121221221321421580 unmodified lines2962972982993013003013033023033043053062 unmodified lines30931031131231431331431631531631731831912 unmodified lines332333334335337336337338339340341342343344345346347348349111 unmodified linesExpand all46146246346446346546646746824 unmodified lines49349449549649649749849950072 unmodified lines57357457557657757857958058188 unmodified lines670671672673674675676677678679680681682683684685686863 unmodified linesExpand all15501551155215531554155515561557155815591560140 unmodified linesExpand all170117021703170417051706170717081709171017111712171317149 unmodified lines1724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177644 unmodified lines18211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518664 unmodified lines1871187218731874187518761877187818791880188118821883188472 unmodified lines195719581959196019611962196319641965196619671968196919701971197219731974186119751976197719781979198021 unmodified lines200220032004200520062007200820092010201120122013125 unmodified linesExpand all156 unmodified linesExpand all grid-template-columns: 15.5rem minmax(0, 1fr) 29.5rem; gap: 1rem; align-items: center; padding: 0.5rem; background: rgb(249 250 251); background: rgb(241 245 249);}
.untangled-pr-diff-toolbar-sidebar-collapsed { grid-template-columns: minmax(0, 1fr) 29.5rem;42 unmodified lines.untangled-pr-diff-toolbar-sidebar-collapsed .untangled-pr-diff-toolbar-history { grid-column: 2;}
.untangled-pr-tool-button,.untangled-pr-sidebar-toggle { display: inline-flex; min-height: 2.125rem; align-items: center;80 unmodified lines min-width: 0;}
.untangled-pr-file-tree-children { margin-left: 1rem; margin-left: 0.25rem; border-left: 1px solid rgb(209 213 219); padding-left: 0.75rem; padding-left: 0.5rem;}
.untangled-pr-file-tree-entry { display: flex;2 unmodified lines gap: 0.375rem; min-height: 1.5rem; border-radius: 0.25rem; padding-top: 0.125rem; padding-right: 0.5rem; padding-right: 0.25rem; padding-bottom: 0.125rem; padding-left: 0.25rem; padding-left: 0; color: rgb(55 65 81); font-size: 0.875rem; text-decoration: none;}12 unmodified lines}
.untangled-pr-diff-file { scroll-margin-top: 4rem; overflow: hidden; overflow: visible; border: 1px solid rgb(209 213 219); border-radius: 0.25rem; background: rgb(255 255 255);}
.untangled-pr-diff-file-header { position: sticky; top: 3rem; z-index: 20; display: flex; min-height: 2.75rem; cursor: pointer; list-style: none;111 unmodified linesExpand all}
@media (prefers-color-scheme: dark) { .untangled-pr-summary-card, .untangled-pr-tool-button, .untangled-pr-sidebar-toggle, .untangled-pr-file-tree, .untangled-pr-diff-file, .untangled-pr-history-card {24 unmodified lines border-color: rgb(55 65 81); color: rgb(156 163 175); }
.untangled-pr-tool-button, .untangled-pr-sidebar-toggle, .untangled-pr-diff-file, .untangled-pr-history-card { border-color: rgb(55 65 81);72 unmodified lines
.untangled-pr-file-tree { display: none; }
}
@media (max-width: 767px) { .untangled-pr-diff-toolbar {88 unmodified lines max-width: 1126px; padding-bottom: max(2rem, calc(1.5rem + env(safe-area-inset-bottom)));}
.untangled-repo-frame-full { box-sizing: border-box; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); padding-left: 0.25rem; padding-right: 0.25rem; width: 100vw;}
.untangled-skeleton { background: rgb(229 231 235); position: relative; overflow: hidden;863 unmodified linesExpand all.untangled-code-line-number { width: 1%; padding: 0 0.75rem 0 0.5rem; color: var(--untangled-code-muted); overflow-wrap: normal; white-space: nowrap; word-break: normal; text-align: right; text-decoration: none; user-select: none;}140 unmodified linesExpand all flex-direction: column; gap: 0;}
.untangled-commit-view,.untangled-commit-diff,.untangled-diff-view-commit { width: 100%;}
.untangled-diff-panel { overflow: hidden; border: 1px solid rgb(229 231 235); border-radius: 0.25rem;9 unmodified lines border-bottom: 1px solid rgb(229 231 235); padding: 0.5rem 0.75rem;}
.untangled-diff-sidebar-toggle { display: inline-flex; width: 2rem; min-height: 2rem; align-items: center; justify-content: center; border: 1px solid rgb(209 213 219); border-radius: 0.25rem; background: rgb(255 255 255); color: rgb(31 41 55);}
.untangled-diff-view-commit .untangled-diff-toolbar { background: rgb(241 245 249);}
.untangled-diff-view-commit .untangled-diff-panel { overflow: visible; border: 0; border-radius: 0; background: transparent;}
.untangled-diff-view-commit .untangled-diff-toolbar { border-bottom: 0; position: sticky; top: 0; z-index: 30; min-height: 3rem; padding: 0.5rem 0;}
.untangled-diff-view-commit .untangled-diff-panel-body { padding-top: 0; padding-left: 0; padding-right: 0;}
.untangled-diff-files { display: flex; min-width: 0; flex-direction: column; gap: 0.5rem;}
.untangled-diff-tool-button,.untangled-diff-mode-button { display: inline-flex; align-items: center;44 unmodified lines gap: 0.5rem; padding: 0.5rem;}
.untangled-diff-panel-body.untangled-diff-panel-body-with-tree { display: grid; grid-template-columns: 15.5rem minmax(0, 1fr); align-items: start; gap: 1rem;}
.untangled-diff-view-commit .untangled-diff-panel-body.untangled-diff-panel-body-with-tree { padding-top: 0;}
.untangled-diff-view-commit .untangled-pr-file-tree { top: 3rem; max-height: calc(100vh - 3rem); min-height: calc(100vh - 3rem); border-top: 1px solid rgb(229 231 235); border-radius: 0.25rem;}
@media (max-width: 1023px) { .untangled-diff-panel-body.untangled-diff-panel-body-with-tree { display: flex; grid-template-columns: none; }}
.untangled-diff-file { overflow: hidden; border: 1px solid rgb(229 231 235); border-radius: 0.25rem; background: rgb(255 255 255);}
.untangled-diff-view-commit .untangled-diff-file { scroll-margin-top: 4rem; overflow: visible;}
.untangled-diff-file-header { display: flex; align-items: center; justify-content: space-between;4 unmodified lines border-bottom: 1px solid rgb(229 231 235); list-style: none;}
.untangled-diff-view-commit .untangled-diff-file-header { position: sticky; top: 3rem; z-index: 20;}
.untangled-diff-file-header::-webkit-details-marker { display: none;}
72 unmodified lines border-bottom-color: rgb(55 65 81); background: rgb(55 65 81 / 0.5); }
.untangled-diff-view-commit .untangled-diff-toolbar { background: rgb(17 24 39); }
.untangled-diff-view-commit .untangled-diff-panel { border: 0; background: transparent; }
.untangled-diff-view-commit .untangled-pr-file-tree { border-top-color: rgb(55 65 81); }
.untangled-diff-tool-button, .untangled-diff-mode-button { .untangled-diff-mode-button, .untangled-diff-sidebar-toggle { border-color: rgb(55 65 81); background: rgb(17 24 39 / 0.35); color: rgb(229 231 235); }21 unmodified lines border-bottom-color: rgb(55 65 81); background: rgb(17 24 39 / 0.35); }
.untangled-diff-view-commit .untangled-diff-file-header { background: rgb(31 41 55); }
.untangled-diff-show-more-summary { color: rgb(209 213 219); }}125 unmodified linesExpand all2 unmodified lines345678910111219 unmodified lines32333435363738394041422 unmodified lines2 unmodified lines
import { RootShell } from './layout';import { BlobPage, CommitPage, CommitsPage, IssuePage, IssuesPage, NewIssuePage, NewPullPage,19 unmodified lines <Route path="/issues" component={IssuesPage} /> <Route path="/pulls/new" component={NewPullPage} /> <Route path="/pulls/:pullRef" component={PullPage} /> <Route path="/pulls" component={PullsPage} /> <Route path="/commits" component={CommitsPage} /> <Route path="/commits/:ref" component={CommitsPage} /> <Route path="/commit/:ref" component={CommitPage} /> <Route path="/blob/:ref/*path" component={BlobPage} /> <Route path="/tree/:ref/*path" component={RepoCodePage} /> </Route> <Route path="*404" component={NotFoundPage} />2 unmodified lines8 unmodified lines91011121313141516401 unmodified linesExpand all41841942042142242342442542642742842942842943043143243343443543643243343443543643743843944044144244344444544644744844945045145245345445545645745845911 unmodified lines471472473474463475476477478479480481482483484485486487488489319 unmodified linesExpand all8098108118127918138148158168178188198208218228238248258268278288298308318328338348358368378388398407948418428437967978448458468478488498008508518528538048058068078548558568578588598608618628638648658668678688698108118128138148158708718728738744 unmodified lines879880881882883884885886887888889828829830831832833890891892893894895896897898899900901902903904905906907908909835836837910911912913914915916917918919920921922923924925926927839928929930931932933841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875934935936937938939940941942150 unmodified linesExpand all10931094109510961034103510971098109911001101110211031104104310441045104611051106110711081109112 unmodified linesExpand all8 unmodified lines ExternalLink, FileText, FoldVertical, Folder, Minimize2, PanelLeftClose, PanelLeftOpen, PanelRightClose, PanelRightOpen,401 unmodified linesExpand all name: string; href: string; icon: JSX.Element; lastCommit?: TreeEntry['last_commit']; lastCommitHref?: string; class?: string; onMouseEnter?: JSX.EventHandlerUnion<HTMLAnchorElement, MouseEvent>; onMouseLeave?: JSX.EventHandlerUnion<HTMLAnchorElement, MouseEvent>; onClick?: JSX.EventHandlerUnion<HTMLAnchorElement, MouseEvent>;}> = (props) => ( <A href={props.href} class={clsx('untangled-file-row hover:underline', props.class)} onClick={props.onClick} onMouseEnter={props.onMouseEnter} onMouseLeave={props.onMouseLeave}> <div class="flex min-w-0 items-center gap-2"> <div class={clsx('untangled-file-row', props.class)}> <A href={props.href} class="flex min-w-0 items-center gap-2 no-underline hover:underline dark:text-white" onClick={props.onClick} onMouseEnter={props.onMouseEnter} onMouseLeave={props.onMouseLeave}> {props.icon} <span class="truncate">{props.name}</span> </div> <span class="untangled-file-row-time text-sm text-gray-500 dark:text-gray-400"> {props.lastCommit?.when ? formatRelativeTime(props.lastCommit.when) : ''} </span> </A> </A> <Show when={props.lastCommit?.when}> {(when) => ( <Show when={props.lastCommitHref} fallback={<span class="untangled-file-row-time text-sm text-gray-500 dark:text-gray-400">{formatRelativeTime(when())}</span>} > {(href) => ( <A href={href()} class="untangled-file-row-time text-sm text-gray-500 no-underline hover:underline dark:text-gray-400"> {formatRelativeTime(when())} </A> )} </Show> )} </Show> </div>);
export const FileRow: Component<{ name: string; href: string; icon: JSX.Element; lastCommit?: TreeEntry['last_commit']; lastCommitHref?: string; commitMessage?: string;}> = (props) => ( <div class="grid grid-cols-12 gap-4 items-center py-1"> <div class="col-span-8 md:col-span-4">11 unmodified lines </div> </Show> </div> <div class="col-span-4 md:col-span-2 text-sm text-right text-gray-500 dark:text-gray-400"> {props.lastCommit ? formatRelativeTime(props.lastCommit.when) : ''} <Show when={props.lastCommit?.when}> {(when) => ( <Show when={props.lastCommitHref} fallback={<span>{formatRelativeTime(when())}</span>}> {(href) => ( <A href={href()} class="text-gray-500 no-underline hover:underline dark:text-gray-400"> {formatRelativeTime(when())} </A> )} </Show> )} </Show> </div> </div>);
319 unmodified linesExpand all pushCurrent(); return files;};
export const DiffView: Component<{ patch: string; maxHeight?: string; wrap?: boolean }> = (props) => {const changedFilesLabel = (count: number) => `${count} changed file${count === 1 ? '' : 's'}`;
const DiffToolbarStats: Component<{ additions: number; deletions: number; fileCount: number; class?: string }> = (props) => ( <> <DiffStatPill additions={props.additions} deletions={props.deletions} /> <span class={props.class ?? 'text-xs text-gray-600 dark:text-gray-300'}>{changedFilesLabel(props.fileCount)}</span> </>);
const DiffCollapseButton: Component<{ expanded: boolean; onToggle: () => void }> = (props) => ( <button type="button" class="untangled-diff-tool-button" onClick={props.onToggle}> <Show when={props.expanded} fallback={<UnfoldVertical class="size-4" />}> <FoldVertical class="size-4" /> </Show> <span>{props.expanded ? 'collapse all' : 'expand all'}</span> </button>);
export const DiffView: Component<{ patch: string; maxHeight?: string; wrap?: boolean; defaultExpanded?: boolean; showFileTree?: boolean; variant?: 'default' | 'commit';}> = (props) => { const files = createMemo(() => parseDiffFiles(props.patch)); const stats = createMemo(() => totalDiffStats(files())); const [expanded, setExpanded] = createSignal(false); const [expanded, setExpanded] = createSignal(props.defaultExpanded ?? false); const [filesVisible, setFilesVisible] = createSignal(true); const previewLimit = 5; const visibleFiles = createMemo(() => files().slice(0, previewLimit)); const hiddenFiles = createMemo(() => files().slice(previewLimit)); const showFileTree = createMemo(() => Boolean(props.showFileTree && files().length > 0)); const tree = createMemo(() => diffFileTree(files())); const visibleFiles = createMemo(() => (showFileTree() ? files() : files().slice(0, previewLimit))); const hiddenFiles = createMemo(() => (showFileTree() ? [] : files().slice(previewLimit)));
return ( <div class="untangled-diff-view"> <div class={clsx('untangled-diff-view', props.variant === 'commit' && 'untangled-diff-view-commit')}> <div class="untangled-diff-panel"> <div class="untangled-diff-toolbar"> <div class="flex min-w-0 items-center gap-2"> <DiffStatPill additions={stats().additions} deletions={stats().deletions} /> <span class="text-xs text-gray-600 dark:text-gray-300"> {files().length} changed file{files().length === 1 ? '' : 's'} </span> <Show when={showFileTree()}> <button type="button" class="untangled-diff-sidebar-toggle" aria-label={filesVisible() ? 'collapse changed files sidebar' : 'expand changed files sidebar'} aria-pressed={filesVisible()} onClick={() => setFilesVisible(!filesVisible())} > <Show when={filesVisible()} fallback={<PanelLeftOpen class="size-4" />}> <PanelLeftClose class="size-4" /> </Show> </button> </Show> <DiffToolbarStats additions={stats().additions} deletions={stats().deletions} fileCount={files().length} /> </div> <div class="flex items-center gap-2"> <button type="button" class="untangled-diff-tool-button" onClick={() => setExpanded(!expanded())}> <Show when={expanded()} fallback={<UnfoldVertical class="w-4 h-4" />}> <FoldVertical class="w-4 h-4" /> </Show> {expanded() ? 'Collapse all' : 'Expand all'} </button> <DiffCollapseButton expanded={expanded()} onToggle={() => setExpanded(!expanded())} /> <div class="untangled-diff-mode-group"> <button type="button" class="untangled-diff-mode-button untangled-diff-mode-button-active"> <FileText class="w-4 h-4" /> unified4 unmodified lines </button> </div> </div> </div> <div class={clsx('untangled-diff-panel-body', showFileTree() && filesVisible() && 'untangled-diff-panel-body-with-tree')}> <Show when={showFileTree() && filesVisible()}> <aside class="untangled-pr-file-tree" aria-label="changed files"> <DiffFileTreeNodes nodes={tree()} /> </aside> </Show>
<div class="untangled-diff-panel-body"> <For each={visibleFiles()}> {(file) => ( <details class="untangled-diff-file" open={expanded()}> <summary class="untangled-diff-file-header"> <div class="flex min-w-0 items-center gap-2"> <div class={showFileTree() ? 'untangled-pr-diff-files' : 'untangled-diff-files'}> <For each={visibleFiles()}> {(file) => ( <details id={diffFileElementId(file.path)} class="untangled-diff-file" open={expanded()}> <summary class="untangled-diff-file-header"> <div class="flex min-w-0 items-center gap-2"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> <DiffStatPill additions={file.additions} deletions={file.deletions} /> <span class="truncate font-mono text-sm text-gray-900 dark:text-gray-100">{file.path}</span> </div> </summary> <CodeView text={file.text} wrap={props.wrap} maxHeight={props.maxHeight} diff path={file.path} /> </details> )} </For> <Show when={hiddenFiles().length > 0}> <details class="untangled-diff-show-more"> <summary class="untangled-diff-show-more-summary"> <span class="untangled-diff-show-more-closed"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> <DiffStatPill additions={file.additions} deletions={file.deletions} /> <span class="truncate font-mono text-sm text-gray-900 dark:text-gray-100">{file.path}</span> </div> Show {hiddenFiles().length} more file{hiddenFiles().length === 1 ? '' : 's'} </span> <span class="untangled-diff-show-more-open"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> Hide {hiddenFiles().length} file{hiddenFiles().length === 1 ? '' : 's'} </span> </summary> <div class="untangled-diff-show-more-files"> <For each={hiddenFiles()}> {(file) => ( <details id={diffFileElementId(file.path)} class="untangled-diff-file" open={expanded()}> <summary class="untangled-diff-file-header"> <div class="flex min-w-0 items-center gap-2"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> <DiffStatPill additions={file.additions} deletions={file.deletions} /> <span class="truncate font-mono text-sm text-gray-900 dark:text-gray-100">{file.path}</span> </div> </summary> <CodeView text={file.text} wrap={props.wrap} maxHeight={props.maxHeight} diff path={file.path} /> <CodeView text={file.text} wrap={props.wrap} maxHeight={props.maxHeight} diff path={file.path} /> </details> )} </For> </div> </details> )} </For> <Show when={hiddenFiles().length > 0}> <details class="untangled-diff-show-more"> <summary class="untangled-diff-show-more-summary"> <span class="untangled-diff-show-more-closed"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> Show {hiddenFiles().length} more file{hiddenFiles().length === 1 ? '' : 's'} </span> <span class="untangled-diff-show-more-open"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> Hide {hiddenFiles().length} file{hiddenFiles().length === 1 ? '' : 's'} </span> </summary> <div class="untangled-diff-show-more-files"> <For each={hiddenFiles()}> {(file) => ( <details class="untangled-diff-file" open={expanded()}> <summary class="untangled-diff-file-header"> <div class="flex min-w-0 items-center gap-2"> <ChevronRight class="untangled-diff-chevron size-4 shrink-0" /> <DiffStatPill additions={file.additions} deletions={file.deletions} /> <span class="truncate font-mono text-sm text-gray-900 dark:text-gray-100">{file.path}</span> </div> </summary> <CodeView text={file.text} wrap={props.wrap} maxHeight={props.maxHeight} diff path={file.path} /> </details> )} </For> </div> </details> </Show> <Show when={files().length === 0}> <div class="px-4 py-8 text-center text-sm text-gray-400">No differences found.</div> </Show> </Show> <Show when={files().length === 0}> <div class="px-4 py-8 text-center text-sm text-gray-400">No differences found.</div> </Show> </div> </div> </div> </div> );150 unmodified linesExpand all <Show when={filesVisible()} fallback={<PanelLeftOpen class="size-4" />}> <PanelLeftClose class="size-4" /> </Show> </button> <DiffStatPill additions={stats().additions} deletions={stats().deletions} /> <span>{files().length} changed files</span> <DiffToolbarStats additions={stats().additions} deletions={stats().deletions} fileCount={files().length} class="text-xs text-gray-600 dark:text-gray-400" /> <span class="hidden h-5 w-px bg-gray-300 dark:bg-gray-700 sm:inline-block" /> <span class="uppercase tracking-wide">diff</span> <span class="rounded border border-gray-300 px-2 py-0.5 font-mono text-xs text-gray-700 dark:border-gray-600 dark:text-gray-200"> {props.roundLabel} </span> </div> <div class="untangled-pr-diff-toolbar-actions"> <button type="button" class="untangled-pr-tool-button" onClick={() => setExpanded(!expanded())}> <Minimize2 class="size-4" /> <span>{expanded() ? 'collapse all' : 'expand all'}</span> </button> <DiffCollapseButton expanded={expanded()} onToggle={() => setExpanded(!expanded())} /> </div> <div class="untangled-pr-diff-toolbar-history"> <button type="button"112 unmodified linesExpand all19 unmodified lines20212223242526272844 unmodified lines737475767778798081828384858687888990919293949523 unmodified lines19 unmodified linesexport { buildBlobDataUrl, compareBranches, decodeBlobText, getRepoCommit, getRepo, getRepoBlob, getRepoBranches, getRepoByDid,44 unmodified lines BlobResponse, BranchEntry, BranchResponse, CommitHeadline, CommitEntry, ComparePatch, CompareResponse, DefaultBranchResponse, DiffTextFragment, DiffTextLine, GitHashValue, LanguageResponse, LogResponse, RepoCommitResponse, RepoContext, RepoDiff, RepoDiffFile, RepoDiffStat, RepoLogOptions, RepoRecord, TagResponse, TreeEntry, TreeResponse,23 unmodified lines89 unmodified lines90919293949596979899100101102103132 unmodified linesExpand all89 unmodified lines
export const blobHref = (repo: RepoContext, ref: string, path: string): string => `/${repo.owner.handle}/${repo.slug}/blob/${encodeURIComponent(ref)}/${encodePath(path)}`;
export const commitsHref = (repo: RepoContext, ref: string): string => `/${repo.owner.handle}/${repo.slug}/commits/${encodeURIComponent(ref)}`;
export const commitHref = (repo: RepoContext, ref: string): string => `/${repo.owner.handle}/${repo.slug}/commit/${encodeURIComponent(ref)}`;
const encodeRouteParam = (value: string | number): string => encodeURIComponent(String(value));
export const issueHref = (repo: RepoContext, issueRef: string | number): string => `/${repo.owner.handle}/${repo.slug}/issues/${encodeRouteParam(issueRef)}`;132 unmodified linesExpand all1234export { BlobPage, RepoCodePage } from './repo/code';export { CommitPage, CommitsPage } from './repo/commits';export { IssuePage, IssuesPage, NewIssuePage } from './repo/issues';export { NewPullPage, PullPage, PullsPage } from './repo/pulls';128 unmodified linesExpand all129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164139140141142143144145146147148149150151152153154155165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219221 unmodified linesExpand all44144244344438744544644744844945045145245345445545645745845946039346146246346446546646746846947047147247347447547647747847948048148248348448548657 unmodified lines54454554654746454854955055155255346646755455555655755855956056156256356456556656756856957040 unmodified lines128 unmodified linesExpand all color?: string; }>;}
export type GitHashValue = | string | number[] | { String?: string; string?: string; };
export interface CommitSignature { Name: string; Email: string; When: string;}
export interface CommitEntry { hash?: GitHashValue; this: string; message: string; tree?: string; author?: CommitSignature; committer?: CommitSignature; pgp_signature?: string; parent?: string; parent_hashes?: GitHashValue[];}
export interface LogResponse { ref: string; total: number; page: number; per_page: number; log: boolean; commits: Array<{ this: string; message: string; author?: { Name: string; Email: string; When: string; }; committer?: { Name: string; Email: string; When: string; }; pgp_signature?: string; parent?: string; parent_hashes?: number[][]; }>; commits: CommitEntry[];}
export interface DiffTextLine { Op: 0 | 1 | 2 | ' ' | '-' | '+'; Line: string;}
export interface DiffTextFragment { Comment?: string; OldPosition: number; OldLines: number; NewPosition: number; NewLines: number; LinesAdded: number; LinesDeleted: number; LeadingContext?: number; TrailingContext?: number; Lines: DiffTextLine[];}
export interface RepoDiffFile { name: { old: string; new: string; }; text_fragments: DiffTextFragment[]; is_binary: boolean; is_new: boolean; is_delete: boolean; is_copy: boolean; is_rename: boolean;}
export interface RepoDiffStat { insertions: number; deletions: number; files_changed: number;}
export interface RepoDiff { commit: CommitEntry; stat: RepoDiffStat; diff: RepoDiffFile[];}
export interface RepoCommitResponse { ref: string; diff?: RepoDiff;}
export interface BlobResponse { path: string; ref: string; content?: string;221 unmodified linesExpand all }, }), )) as LanguageResponse;
const getRepoLogFromKnot = async (repo: RepoContext, ref: string): Promise<LogResponse> =>export interface RepoLogOptions { limit?: number; cursor?: string; path?: string;}
const getRepoLogFromKnot = async ( repo: RepoContext, ref: string, options: RepoLogOptions = {},): Promise<LogResponse> => (await ok( getRpc(repo.knot).get('sh.tangled.repo.log', { params: { repo: repo.repoDid, ref, limit: 8, limit: options.limit ?? 8, ...(options.cursor ? { cursor: options.cursor } : {}), ...(options.path ? { path: options.path } : {}), }, as: 'json', }), )) as LogResponse;
const getRepoCommitFromKnot = async ( repo: RepoContext, ref: string,): Promise<RepoCommitResponse> => (await ok( getRpc(repo.knot).get('sh.tangled.repo.diff', { params: { repo: repo.repoDid, ref, }, as: 'json', }), )) as RepoCommitResponse;
const getRepoBlobFromKnot = async ( repo: RepoContext, ref: string, path: string,57 unmodified lines () => getRepoViaAppview<LanguageResponse>('sh.tangled.repo.languages', repo, { ref }), () => getRepoLanguagesFromKnot(repo, ref), );
export const getRepoLog = async (repo: RepoContext, ref: string): Promise<LogResponse> =>export const getRepoLog = async ( repo: RepoContext, ref: string, options: RepoLogOptions = {},): Promise<LogResponse> => appviewOptionalKnotRequest( () => getRepoViaAppview<LogResponse>('sh.tangled.repo.log', repo, { ref, limit: 8 }), () => getRepoLogFromKnot(repo, ref), () => getRepoViaAppview<LogResponse>('sh.tangled.repo.log', repo, { ref, ...options, limit: options.limit ?? 8 }), () => getRepoLogFromKnot(repo, ref, options), );
export const getRepoCommit = async ( repo: RepoContext, ref: string,): Promise<RepoCommitResponse> => appviewOptionalKnotRequest( () => getRepoViaAppview<RepoCommitResponse>('sh.tangled.repo.diff', repo, { ref }), () => getRepoCommitFromKnot(repo, ref), );
export const getRepoBlob = async ( repo: RepoContext, ref: string, path: string,40 unmodified lines5 unmodified lines6789101011121314377 unmodified linesExpand all392393394395396397398399400311 unmodified linesExpand all71271371471571671771871972015 unmodified lines736737738739738740741742743744745744746747748749750265 unmodified linesExpand all5 unmodified linesimport { buildBlobDataUrl, decodeBlobText, getRepoBlob, getRepoBranches, getRepoDefaultBranch, getRepoLanguages, getRepoLog, getRepoTags, getRepoTree } from '../../lib/api/repos';import { Avatar, ErrorState, PlaceholderAvatar, buttonStyles, cardStyles } from '../../components/common';import { CodeView, FileRow, MarkdownBlock, OverviewFileRow, ReadmeCard, RepoTreeSkeleton } from '../../components/repo';import { RepoFrame, useRepoQuery } from './shared';import { blobHref, countLines, decodeRoutePath, formatBytes, formatLanguagePercent, formatRelativeTime, getErrorMessage, getParentPath, imageLike, isDirectory, joinPath, languageColor, markdownLike, safeDecode, sortedTreeEntries, svgLike, treeHref, videoLike } from '../../lib/repo-utils';import { blobHref, commitHref, commitsHref, countLines, decodeRoutePath, formatBytes, formatLanguagePercent, formatRelativeTime, getErrorMessage, getParentPath, imageLike, isDirectory, joinPath, languageColor, markdownLike, safeDecode, sortedTreeEntries, svgLike, treeHref, videoLike } from '../../lib/repo-utils';import { LOADING_DELAY_MS, hasNamedRef, normalizeLanguages, resolveDefaultBranchName, resolveRouteRefAndPath, shouldAnimateNavigation, useDelayedLoading } from './code-helpers';
const PathBreadcrumbs: Component<{ repo: Parameters<typeof treeHref>[0];377 unmodified linesExpand all <File class="size-4 flex-shrink-0" /> ) } lastCommit={entry.last_commit} lastCommitHref={entry.last_commit ? commitHref(repo, entry.last_commit.hash) : undefined} commitMessage={entry.last_commit?.message} /> )} </For>311 unmodified linesExpand all <File class="size-4 flex-shrink-0" /> ) } lastCommit={entry.last_commit} lastCommitHref={entry.last_commit ? commitHref(repo, entry.last_commit.hash) : undefined} class={pendingTreeHref() === href ? 'untangled-file-row-loading' : undefined} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} onClick={(event) => {15 unmodified lines </div>
<Show when={!isNestedTreePath}> <div class="min-w-0 md:pt-0 md:pl-6 border-gray-100 dark:border-gray-700 md:border-t-0 md:border-l"> <div class="flex items-center gap-2 pb-3 font-bold"> <A href={commitsHref(repo, activeRef)} class="flex items-center gap-2 pb-3 font-bold no-underline hover:underline dark:text-white"> <List class="size-4" /> <span>commits</span> <span class="rounded bg-gray-200 px-1 py-0.5 text-sm font-normal dark:bg-gray-700"> {logQuery.data?.total ?? commits.length} </span> </div> </A> <div class="space-y-6"> <For each={commits.slice(0, 6)}> {(commit) => ( <div>265 unmodified linesExpand all52 unmodified lines535455565758596061133 unmodified linesExpand all195196197198199198200201202203204205206207208209207210211212213214155 unmodified linesExpand all3703713723733713743753763773781 unmodified line52 unmodified lines
export const RepoFrame: Component<{ active: 'code' | 'issues' | 'pulls'; children: JSX.Element; fullWidth?: boolean;}> = (props) => { const auth = useAuth(); const live = useLiveEvents(); const repoQuery = useRepoQuery();133 unmodified linesExpand all
return ( <Switch> <Match when={repoQuery.isLoading}> <div class={props.fullWidth ? 'untangled-repo-frame-full' : undefined}> <RepoFrameSkeleton active={props.active} /> <RepoFrameSkeleton active={props.active} /> </div> </Match> <Match when={repoQuery.error}> <div class={cardStyles('p-6')}> <ErrorState message={getErrorMessage(repoQuery.error)} /> </div> </Match> <Match when={repoQuery.data}> {(repo) => ( <> <div class={props.fullWidth ? 'untangled-repo-frame-full' : undefined}> <section id="repo-header" class="mb-2 py-2 px-4"> <div class="flex flex-col sm:flex-row items-start gap-4 justify-between mb-2"> <div class="flex gap-2"> <div class="flex items-center gap-2 flex-wrap text-lg">155 unmodified linesExpand all </nav>
{props.children} </section> </> </div> )} </Match> </Switch> );1 unmodified line