Browse Source

fix build

Nostr-Signature: 830b91f4efe7d208128a008d44fd3b4352c09af0a83b40ea1fab769f9c8563cf 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc 49a9772580d5ba1b9b9800bdb53f0f4b55661f6062f9968b18cbbd4983d7a042b477281769488d44b4f43c7bdf627d621d83c16659d3d8d226fb32fe0a450756
main
Silberengel 2 months ago
parent
commit
89df3e4341
  1. 1
      nostr/commit-signatures.jsonl
  2. 293
      scripts/migrate-repo-state.js
  3. 3143
      src/routes/repos/[npub]/[repo]/+page.svelte
  4. 6619
      src/routes/repos/[npub]/[repo]/+page.svelte.backup
  5. 2
      src/routes/repos/[npub]/[repo]/hooks/use-repo-data.ts
  6. 746
      src/routes/repos/[npub]/[repo]/stores/repo-state.ts

1
nostr/commit-signatures.jsonl

@ -90,3 +90,4 @@ @@ -90,3 +90,4 @@
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772010107,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"968af17f95f1ba0cf6a4d1f04ce108a6e4eb4ec3a4f72ca6a9d2529dacb92811","sig":"1891b6131effda70ec76577efadd9ea7374ebcbd4d738d0b0650e7dce46c3e7253eccb4b8455690297b63b7c30f61a0c7dcc1af0147b2f5a631bbd91c517c32b"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772011169,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","prevent zombie git processes"]],"content":"Signed commit: prevent zombie git processes","id":"fd370d2613105f16b0cfdd55b33f50c5b724ecef272109036a7cce5477da29bc","sig":"1d3cb4392f722b1b356247bde64691576d41fdb697e8dfe62d5e7ecd5ad8ea35757da2d56db310a2005e4b5528013aa1205256e37fc230f024d3b5a2e26735bf"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772087425,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","refactoring 1"]],"content":"Signed commit: refactoring 1","id":"533e9f7acbdd4dc16dbe304245469d57d8d37f0c0cce53b60d99719e2acf4502","sig":"0fad2d7c44f086ceb06ce40ea8cea2d4d002ebe8caec7d78e83483348b1404cfb6256d8d3796ebd9ae6f7866a431ec4a1abe84e417d3e238b9b554b4a32481e4"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772090269,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","refactoring 2"]],"content":"Signed commit: refactoring 2","id":"9375bfe35e0574bc722cad243c22fdf374dcc9016f91f358ff9ddf1d0a03bb50","sig":"10fbbcbc7cab48dfd2340f0c9eceafe558d893789e4838cbe26493e5c339f7a1f015d1cc4af8bfa51d57e9a9da94bb1bb44841305d5ce7cf92db9938985d0459"}

293
scripts/migrate-repo-state.js

@ -0,0 +1,293 @@ @@ -0,0 +1,293 @@
#!/usr/bin/env node
/**
* Migration script to update state references in +page.svelte
* This helps automate the bulk replacement of old state variable references
* with the new nested state structure.
*/
import { readFileSync, writeFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const rootDir = join(__dirname, '..');
const targetFile = join(rootDir, 'src/routes/repos/[npub]/[repo]/+page.svelte');
// Migration mappings: old reference -> new reference
const migrations = [
// Loading states
{ pattern: /\bloading\b/g, replacement: 'state.loading.main' },
{ pattern: /\bloadingReadme\b/g, replacement: 'state.loading.readme' },
{ pattern: /\bloadingCommits\b/g, replacement: 'state.loading.commits' },
{ pattern: /\bloadingIssues\b/g, replacement: 'state.loading.issues' },
{ pattern: /\bloadingIssueReplies\b/g, replacement: 'state.loading.issueReplies' },
{ pattern: /\bloadingPRs\b/g, replacement: 'state.loading.prs' },
{ pattern: /\bloadingPatches\b/g, replacement: 'state.loading.patches' },
{ pattern: /\bloadingPatchHighlights\b/g, replacement: 'state.loading.patchHighlights' },
{ pattern: /\bloadingDocs\b/g, replacement: 'state.loading.docs' },
{ pattern: /\bloadingDiscussions\b/g, replacement: 'state.loading.discussions' },
{ pattern: /\bloadingReleases\b/g, replacement: 'state.loading.releases' },
{ pattern: /\bloadingCodeSearch\b/g, replacement: 'state.loading.codeSearch' },
{ pattern: /\bloadingBookmark\b/g, replacement: 'state.loading.bookmark' },
{ pattern: /\bloadingMaintainerStatus\b/g, replacement: 'state.loading.maintainerStatus' },
{ pattern: /\bloadingMaintainers\b/g, replacement: 'state.loading.maintainers' },
{ pattern: /\bloadingReachability\b/g, replacement: 'state.loading.reachability' },
{ pattern: /\bloadingVerification\b/g, replacement: 'state.loading.verification' },
// UI state
{ pattern: /\bactiveTab\b/g, replacement: 'state.ui.activeTab' },
{ pattern: /\bshowRepoMenu\b/g, replacement: 'state.ui.showRepoMenu' },
{ pattern: /\bshowFileListOnMobile\b/g, replacement: 'state.ui.showFileListOnMobile' },
{ pattern: /\bshowLeftPanelOnMobile\b/g, replacement: 'state.ui.showLeftPanelOnMobile' },
{ pattern: /\bwordWrap\b/g, replacement: 'state.ui.wordWrap' },
{ pattern: /\bexpandedThreads\b/g, replacement: 'state.ui.expandedThreads' },
// User state
{ pattern: /\buserPubkey\b/g, replacement: 'state.user.pubkey' },
{ pattern: /\buserPubkeyHex\b/g, replacement: 'state.user.pubkeyHex' },
// Files
{ pattern: /\bfiles\b/g, replacement: 'state.files.list' },
{ pattern: /\bcurrentPath\b/g, replacement: 'state.files.currentPath' },
{ pattern: /\bcurrentFile\b/g, replacement: 'state.files.currentFile' },
{ pattern: /\bfileContent\b/g, replacement: 'state.files.content' },
{ pattern: /\bfileLanguage\b/g, replacement: 'state.files.language' },
{ pattern: /\beditedContent\b/g, replacement: 'state.files.editedContent' },
{ pattern: /\bhasChanges\b/g, replacement: 'state.files.hasChanges' },
{ pattern: /\bpathStack\b/g, replacement: 'state.files.pathStack' },
// Preview
{ pattern: /\breadmeContent\b/g, replacement: 'state.preview.readme.content' },
{ pattern: /\breadmePath\b/g, replacement: 'state.preview.readme.path' },
{ pattern: /\breadmeIsMarkdown\b/g, replacement: 'state.preview.readme.isMarkdown' },
{ pattern: /\breadmeHtml\b/g, replacement: 'state.preview.readme.html' },
{ pattern: /\bhighlightedFileContent\b/g, replacement: 'state.preview.file.highlightedContent' },
{ pattern: /\bfileHtml\b/g, replacement: 'state.preview.file.html' },
{ pattern: /\bshowFilePreview\b/g, replacement: 'state.preview.file.showPreview' },
{ pattern: /\bcopyingFile\b/g, replacement: 'state.preview.copying' },
{ pattern: /\bisImageFile\b/g, replacement: 'state.preview.file.isImage' },
{ pattern: /\bimageUrl\b/g, replacement: 'state.preview.file.imageUrl' },
// Git
{ pattern: /\bbranches\b/g, replacement: 'state.git.branches' },
{ pattern: /\bcurrentBranch\b/g, replacement: 'state.git.currentBranch' },
{ pattern: /\bdefaultBranch\b/g, replacement: 'state.git.defaultBranch' },
{ pattern: /\bcommits\b/g, replacement: 'state.git.commits' },
{ pattern: /\bselectedCommit\b/g, replacement: 'state.git.selectedCommit' },
{ pattern: /\bshowDiff\b/g, replacement: 'state.git.showDiff' },
{ pattern: /\bdiffData\b/g, replacement: 'state.git.diffData' },
{ pattern: /\bverifyingCommits\b/g, replacement: 'state.git.verifyingCommits' },
{ pattern: /\btags\b/g, replacement: 'state.git.tags' },
{ pattern: /\bselectedTag\b/g, replacement: 'state.git.selectedTag' },
// Forms
{ pattern: /\bnewFileName\b/g, replacement: 'state.forms.file.fileName' },
{ pattern: /\bnewFileContent\b/g, replacement: 'state.forms.file.content' },
{ pattern: /\bnewBranchName\b/g, replacement: 'state.forms.branch.name' },
{ pattern: /\bnewBranchFrom\b/g, replacement: 'state.forms.branch.from' },
{ pattern: /\bdefaultBranchName\b/g, replacement: 'state.forms.branch.defaultName' },
{ pattern: /\bnewTagName\b/g, replacement: 'state.forms.tag.name' },
{ pattern: /\bnewTagMessage\b/g, replacement: 'state.forms.tag.message' },
{ pattern: /\bnewTagRef\b/g, replacement: 'state.forms.tag.ref' },
{ pattern: /\bcommitMessage\b/g, replacement: 'state.forms.commit.message' },
{ pattern: /\bnewIssueSubject\b/g, replacement: 'state.forms.issue.subject' },
{ pattern: /\bnewIssueContent\b/g, replacement: 'state.forms.issue.content' },
{ pattern: /\bnewIssueLabels\b/g, replacement: 'state.forms.issue.labels' },
{ pattern: /\bnewPRSubject\b/g, replacement: 'state.forms.pr.subject' },
{ pattern: /\bnewPRContent\b/g, replacement: 'state.forms.pr.content' },
{ pattern: /\bnewPRCommitId\b/g, replacement: 'state.forms.pr.commitId' },
{ pattern: /\bnewPRBranchName\b/g, replacement: 'state.forms.pr.branchName' },
{ pattern: /\bnewPRLabels\b/g, replacement: 'state.forms.pr.labels' },
{ pattern: /\bnewPatchContent\b/g, replacement: 'state.forms.patch.content' },
{ pattern: /\bnewPatchSubject\b/g, replacement: 'state.forms.patch.subject' },
{ pattern: /\bnewReleaseTagName\b/g, replacement: 'state.forms.release.tagName' },
{ pattern: /\bnewReleaseTagHash\b/g, replacement: 'state.forms.release.tagHash' },
{ pattern: /\bnewReleaseNotes\b/g, replacement: 'state.forms.release.notes' },
{ pattern: /\bnewReleaseIsDraft\b/g, replacement: 'state.forms.release.isDraft' },
{ pattern: /\bnewReleaseIsPrerelease\b/g, replacement: 'state.forms.release.isPrerelease' },
{ pattern: /\bnewThreadTitle\b/g, replacement: 'state.forms.discussion.threadTitle' },
{ pattern: /\bnewThreadContent\b/g, replacement: 'state.forms.discussion.threadContent' },
{ pattern: /\breplyContent\b/g, replacement: 'state.forms.discussion.replyContent' },
{ pattern: /\bselectedPatchText\b/g, replacement: 'state.forms.patchHighlight.text' },
{ pattern: /\bselectedPatchStartLine\b/g, replacement: 'state.forms.patchHighlight.startLine' },
{ pattern: /\bselectedPatchEndLine\b/g, replacement: 'state.forms.patchHighlight.endLine' },
{ pattern: /\bselectedPatchStartPos\b/g, replacement: 'state.forms.patchHighlight.startPos' },
{ pattern: /\bselectedPatchEndPos\b/g, replacement: 'state.forms.patchHighlight.endPos' },
{ pattern: /\bpatchHighlightComment\b/g, replacement: 'state.forms.patchHighlight.comment' },
{ pattern: /\bpatchCommentContent\b/g, replacement: 'state.forms.patchComment.content' },
{ pattern: /\breplyingToPatchComment\b/g, replacement: 'state.forms.patchComment.replyingTo' },
// Dialogs
{ pattern: /\bshowCreateFileDialog\b/g, replacement: "state.openDialog === 'createFile'" },
{ pattern: /\bshowCreateBranchDialog\b/g, replacement: "state.openDialog === 'createBranch'" },
{ pattern: /\bshowCreateTagDialog\b/g, replacement: "state.openDialog === 'createTag'" },
{ pattern: /\bshowCommitDialog\b/g, replacement: "state.openDialog === 'commit'" },
{ pattern: /\bshowCreateIssueDialog\b/g, replacement: "state.openDialog === 'createIssue'" },
{ pattern: /\bshowCreatePRDialog\b/g, replacement: "state.openDialog === 'createPR'" },
{ pattern: /\bshowCreatePatchDialog\b/g, replacement: "state.openDialog === 'createPatch'" },
{ pattern: /\bshowCreateReleaseDialog\b/g, replacement: "state.openDialog === 'createRelease'" },
{ pattern: /\bshowCreateThreadDialog\b/g, replacement: "state.openDialog === 'createThread'" },
{ pattern: /\bshowReplyDialog\b/g, replacement: "state.openDialog === 'reply'" },
{ pattern: /\bshowVerificationDialog\b/g, replacement: "state.openDialog === 'verification'" },
{ pattern: /\bshowCloneUrlVerificationDialog\b/g, replacement: "state.openDialog === 'cloneUrlVerification'" },
{ pattern: /\bshowPatchHighlightDialog\b/g, replacement: "state.openDialog === 'patchHighlight'" },
{ pattern: /\bshowPatchCommentDialog\b/g, replacement: "state.openDialog === 'patchComment'" },
// Selected items
{ pattern: /\bselectedIssue\b/g, replacement: 'state.selected.issue' },
{ pattern: /\bselectedPR\b/g, replacement: 'state.selected.pr' },
{ pattern: /\bselectedPatch\b/g, replacement: 'state.selected.patch' },
{ pattern: /\bselectedDiscussion\b/g, replacement: 'state.selected.discussion' },
// Creating flags
{ pattern: /\bcreatingPatch\b/g, replacement: 'state.creating.patch' },
{ pattern: /\bcreatingThread\b/g, replacement: 'state.creating.thread' },
{ pattern: /\bcreatingReply\b/g, replacement: 'state.creating.reply' },
{ pattern: /\bcreatingRelease\b/g, replacement: 'state.creating.release' },
{ pattern: /\bcreatingPatchHighlight\b/g, replacement: 'state.creating.patchHighlight' },
{ pattern: /\bcreatingPatchComment\b/g, replacement: 'state.creating.patchComment' },
{ pattern: /\bdeletingAnnouncement\b/g, replacement: 'state.creating.announcement' },
// Maintainers
{ pattern: /\bisMaintainer\b/g, replacement: 'state.maintainers.isMaintainer' },
{ pattern: /\ballMaintainers\b/g, replacement: 'state.maintainers.all' },
{ pattern: /\bmaintainersLoaded\b/g, replacement: 'state.maintainers.loaded' },
{ pattern: /\bmaintainersEffectRan\b/g, replacement: 'state.maintainers.effectRan' },
{ pattern: /\blastRepoKey\b/g, replacement: 'state.maintainers.lastRepoKey' },
// Clone
{ pattern: /\bisRepoCloned\b/g, replacement: 'state.clone.isCloned' },
{ pattern: /\bcheckingCloneStatus\b/g, replacement: 'state.clone.checking' },
{ pattern: /\bcloning\b/g, replacement: 'state.clone.cloning' },
{ pattern: /\bcopyingCloneUrl\b/g, replacement: 'state.clone.copyingUrl' },
{ pattern: /\bapiFallbackAvailable\b/g, replacement: 'state.clone.apiFallbackAvailable' },
{ pattern: /\bcloneUrlsExpanded\b/g, replacement: 'state.clone.urlsExpanded' },
{ pattern: /\bshowAllCloneUrls\b/g, replacement: 'state.clone.showAllUrls' },
{ pattern: /\bcloneUrlReachability\b/g, replacement: 'state.clone.reachability' },
{ pattern: /\bcheckingReachability\b/g, replacement: 'state.clone.checkingReachability' },
// Verification
{ pattern: /\bverificationStatus\b/g, replacement: 'state.verification.status' },
{ pattern: /\bverificationFileContent\b/g, replacement: 'state.verification.fileContent' },
{ pattern: /\bverifyingCloneUrl\b/g, replacement: 'state.verification.selectedCloneUrl' },
{ pattern: /\bselectedCloneUrlForVerification\b/g, replacement: 'state.verification.selectedCloneUrl' },
// Docs
{ pattern: /\bdocumentationContent\b/g, replacement: 'state.docs.content' },
{ pattern: /\bdocumentationHtml\b/g, replacement: 'state.docs.html' },
{ pattern: /\bdocumentationKind\b/g, replacement: 'state.docs.kind' },
// Code search
{ pattern: /\bcodeSearchQuery\b/g, replacement: 'state.codeSearch.query' },
{ pattern: /\bcodeSearchResults\b/g, replacement: 'state.codeSearch.results' },
{ pattern: /\bcodeSearchScope\b/g, replacement: 'state.codeSearch.scope' },
// Fork/Bookmark
{ pattern: /\bforkInfo\b/g, replacement: 'state.fork.info' },
{ pattern: /\bforking\b/g, replacement: 'state.fork.forking' },
{ pattern: /\bisBookmarked\b/g, replacement: 'state.bookmark.isBookmarked' },
// Metadata
{ pattern: /\brepoAddress\b/g, replacement: 'state.metadata.address' },
{ pattern: /\brepoImage\b/g, replacement: 'state.metadata.image' },
{ pattern: /\brepoBanner\b/g, replacement: 'state.metadata.banner' },
{ pattern: /\brepoOwnerPubkeyState\b/g, replacement: 'state.metadata.ownerPubkey' },
{ pattern: /\breadmeAutoLoadAttempted\b/g, replacement: 'state.metadata.readmeAutoLoadAttempted' },
// Discussion
{ pattern: /\breplyingToThread\b/g, replacement: 'state.discussion.replyingToThread' },
{ pattern: /\breplyingToComment\b/g, replacement: 'state.discussion.replyingToComment' },
{ pattern: /\bdiscussionEvents\b/g, replacement: 'state.discussion.events' },
{ pattern: /\bnostrLinkEvents\b/g, replacement: 'state.discussion.nostrLinkEvents' },
{ pattern: /\bnostrLinkProfiles\b/g, replacement: 'state.discussion.nostrLinkProfiles' },
// Other
{ pattern: /\bpatchEditor\b/g, replacement: 'state.patchEditor' },
{ pattern: /\bsaving\b/g, replacement: 'state.saving' },
{ pattern: /\bisMounted\b/g, replacement: 'state.isMounted' },
{ pattern: /\brepoNotFound\b/g, replacement: 'state.repoNotFound' },
{ pattern: /\berror\b/g, replacement: 'state.error' },
// Status updates
{ pattern: /\bupdatingIssueStatus\b/g, replacement: 'state.statusUpdates.issue' },
{ pattern: /\bupdatingPatchStatus\b/g, replacement: 'state.statusUpdates.patch' },
// Data collections (keep as-is but ensure they're accessed via state)
{ pattern: /\bissues\b/g, replacement: 'state.issues' },
{ pattern: /\bissueReplies\b/g, replacement: 'state.issueReplies' },
{ pattern: /\bprs\b/g, replacement: 'state.prs' },
{ pattern: /\bpatches\b/g, replacement: 'state.patches' },
{ pattern: /\bpatchHighlights\b/g, replacement: 'state.patchHighlights' },
{ pattern: /\bpatchComments\b/g, replacement: 'state.patchComments' },
{ pattern: /\bdiscussions\b/g, replacement: 'state.discussions' },
{ pattern: /\breleases\b/g, replacement: 'state.releases' },
];
// Special cases that need context-aware replacement
const contextAwareReplacements = [
// Dialog assignments
{
pattern: /(showCreateFileDialog|showCreateBranchDialog|showCreateTagDialog|showCommitDialog|showCreateIssueDialog|showCreatePRDialog|showCreatePatchDialog|showCreateReleaseDialog|showCreateThreadDialog|showReplyDialog|showVerificationDialog|showCloneUrlVerificationDialog|showPatchHighlightDialog|showPatchCommentDialog)\s*=\s*(true|false)/g,
replacement: (match, varName, value) => {
const dialogMap = {
showCreateFileDialog: 'createFile',
showCreateBranchDialog: 'createBranch',
showCreateTagDialog: 'createTag',
showCommitDialog: 'commit',
showCreateIssueDialog: 'createIssue',
showCreatePRDialog: 'createPR',
showCreatePatchDialog: 'createPatch',
showCreateReleaseDialog: 'createRelease',
showCreateThreadDialog: 'createThread',
showReplyDialog: 'reply',
showVerificationDialog: 'verification',
showCloneUrlVerificationDialog: 'cloneUrlVerification',
showPatchHighlightDialog: 'patchHighlight',
showPatchCommentDialog: 'patchComment'
};
const dialogType = dialogMap[varName];
return value === 'true' ? `state.openDialog = '${dialogType}'` : `state.openDialog = null`;
}
}
];
function migrateFile(content) {
let migrated = content;
// Apply simple replacements
for (const { pattern, replacement } of migrations) {
migrated = migrated.replace(pattern, replacement);
}
// Apply context-aware replacements
for (const { pattern, replacement } of contextAwareReplacements) {
if (typeof replacement === 'function') {
migrated = migrated.replace(pattern, replacement);
} else {
migrated = migrated.replace(pattern, replacement);
}
}
return migrated;
}
// Read file
console.log(`Reading ${targetFile}...`);
let content = readFileSync(targetFile, 'utf-8');
// Backup original
const backupFile = targetFile + '.backup';
writeFileSync(backupFile, content, 'utf-8');
console.log(`Backup created: ${backupFile}`);
// Migrate
console.log('Applying migrations...');
const migrated = migrateFile(content);
// Write migrated file
writeFileSync(targetFile, migrated, 'utf-8');
console.log(`Migration complete!`);
console.log(`\n Please review the changes carefully.`);
console.log(` Some replacements may need manual adjustment.`);
console.log(` Backup saved to: ${backupFile}`);

3143
src/routes/repos/[npub]/[repo]/+page.svelte

File diff suppressed because it is too large Load Diff

6619
src/routes/repos/[npub]/[repo]/+page.svelte.backup

File diff suppressed because it is too large Load Diff

2
src/routes/repos/[npub]/[repo]/hooks/use-repo-data.ts

@ -59,7 +59,7 @@ export function useRepoParams( @@ -59,7 +59,7 @@ export function useRepoParams(
if (p && state.isMounted) {
const params = p.params as { npub?: string; repo?: string };
if (params) {
if (params.npub && params.npub !== state.userPubkey) {
if (params.npub && params.npub !== state.npub) {
setNpub(params.npub);
}
if (params.repo) {

746
src/routes/repos/[npub]/[repo]/stores/repo-state.ts

@ -1,104 +1,469 @@ @@ -1,104 +1,469 @@
/**
* Repository page state management
* Centralized state to prevent memory leaks and improve performance
* Optimized: Consolidated redundant patterns, grouped related data
* Uses runes-compatible structure for $state
*/
import type { NostrEvent } from '$lib/types/nostr.js';
// Consolidated loading states - more efficient than individual flags
export interface LoadingStates {
main: boolean;
readme: boolean;
commits: boolean;
issues: boolean;
issueReplies: boolean;
prs: boolean;
patches: boolean;
patchHighlights: boolean;
docs: boolean;
discussions: boolean;
releases: boolean;
codeSearch: boolean;
bookmark: boolean;
maintainerStatus: boolean;
maintainers: boolean;
reachability: boolean;
verification: boolean;
repoNotFound: boolean;
}
// Consolidated dialog states - single source of truth
export type DialogType =
| 'createFile'
| 'createBranch'
| 'createTag'
| 'createRelease'
| 'createIssue'
| 'createPR'
| 'createPatch'
| 'createThread'
| 'reply'
| 'commit'
| 'verification'
| 'cloneUrlVerification'
| 'patchHighlight'
| 'patchComment'
| null;
// Consolidated selected items
export interface SelectedItems {
commit: string | null;
tag: string | null;
issue: string | null;
pr: string | null;
patch: string | null;
discussion: string | null;
}
// Form data grouped by domain
export interface FileFormData {
fileName: string;
content: string;
}
export interface BranchFormData {
name: string;
from: string | null;
defaultName: string;
}
export interface TagFormData {
name: string;
message: string;
ref: string;
}
export interface IssueFormData {
subject: string;
content: string;
labels: string[];
}
export interface PRFormData {
subject: string;
content: string;
commitId: string;
branchName: string;
labels: string[];
}
export interface PatchFormData {
content: string;
subject: string;
}
export interface ReleaseFormData {
tagName: string;
tagHash: string;
notes: string;
isDraft: boolean;
isPrerelease: boolean;
}
export interface DiscussionFormData {
threadTitle: string;
threadContent: string;
replyContent: string;
}
export interface PatchHighlightFormData {
text: string;
startLine: number;
endLine: number;
startPos: number;
endPos: number;
comment: string;
}
export interface PatchCommentFormData {
content: string;
replyingTo: string | null;
}
// Status update tracking
export interface StatusUpdates {
issue: Record<string, boolean>;
patch: Record<string, boolean>;
}
// Main state interface
export interface RepoState {
// Loading states
loading: boolean;
// Page/routing
pageData: {
title?: string;
description?: string;
image?: string;
banner?: string;
repoUrl?: string;
announcement?: NostrEvent;
gitDomain?: string;
};
npub: string;
repo: string;
// Core loading/error
loading: LoadingStates;
error: string | null;
repoNotFound: boolean;
// File system state
files: Array<{ name: string; path: string; type: 'file' | 'directory'; size?: number }>;
currentPath: string;
currentFile: string | null;
fileContent: string;
fileLanguage: 'markdown' | 'asciidoc' | 'text';
editedContent: string;
hasChanges: boolean;
saving: boolean;
// File system
files: {
list: Array<{ name: string; path: string; type: 'file' | 'directory'; size?: number }>;
currentPath: string;
currentFile: string | null;
content: string;
language: 'markdown' | 'asciidoc' | 'text';
editedContent: string;
hasChanges: boolean;
pathStack: string[];
};
// Branch state
branches: Array<string | { name: string; commit?: any }>;
currentBranch: string | null;
defaultBranch: string | null;
// File preview/display
preview: {
readme: {
content: string | null;
path: string | null;
isMarkdown: boolean;
html: string;
};
file: {
highlightedContent: string;
html: string;
showPreview: boolean;
isImage: boolean;
imageUrl: string | null;
};
copying: boolean;
};
// Commit state
commitMessage: string;
showCommitDialog: boolean;
// Git operations
git: {
branches: Array<string | { name: string; commit?: any }>;
currentBranch: string | null;
defaultBranch: string | null;
commits: Array<{
hash: string;
message: string;
author: string;
date: string;
files: string[];
verification?: {
valid: boolean;
hasSignature?: boolean;
error?: string;
pubkey?: string;
npub?: string;
authorName?: string;
authorEmail?: string;
timestamp?: number;
eventId?: string;
};
}>;
selectedCommit: string | null;
showDiff: boolean;
diffData: Array<{ file: string; additions: number; deletions: number; diff: string }>;
verifyingCommits: Set<string>;
tags: Array<{ name: string; hash: string; message?: string; date?: number }>;
selectedTag: string | null;
};
// User state
userPubkey: string | null;
userPubkeyHex: string | null;
// Forms
forms: {
file: FileFormData;
branch: BranchFormData;
tag: TagFormData;
issue: IssueFormData;
pr: PRFormData;
patch: PatchFormData;
release: ReleaseFormData;
discussion: DiscussionFormData;
patchHighlight: PatchHighlightFormData;
patchComment: PatchCommentFormData;
commit: {
message: string;
};
};
// UI state
activeTab: 'files' | 'history' | 'tags' | 'issues' | 'prs' | 'docs' | 'discussions' | 'patches' | 'releases' | 'code-search';
showRepoMenu: boolean;
// Navigation
pathStack: string[];
// File creation
showCreateFileDialog: boolean;
newFileName: string;
newFileContent: string;
// Branch creation
showCreateBranchDialog: boolean;
newBranchName: string;
newBranchFrom: string | null;
defaultBranchName: string;
// Commit history
commits: Array<{
hash: string;
message: string;
// Data collections
issues: Array<{
id: string;
subject: string;
content: string;
status: string;
author: string;
date: string;
files: string[];
verification?: {
valid: boolean;
hasSignature?: boolean;
error?: string;
created_at: number;
kind: number;
tags?: string[][];
}>;
issueReplies: Array<{
id: string;
content: string;
author: string;
created_at: number;
tags: string[][];
}>;
prs: Array<{
id: string;
subject: string;
content: string;
status: string;
author: string;
created_at: number;
commitId?: string;
kind: number;
}>;
patches: Array<{
id: string;
subject: string;
content: string;
status: string;
author: string;
created_at: number;
kind: number;
description?: string;
tags?: string[][];
}>;
patchHighlights: Array<{
id: string;
content: string;
pubkey: string;
created_at: number;
highlightedContent?: string;
file?: string;
lineStart?: number;
lineEnd?: number;
comment?: string;
comments?: Array<{
id: string;
content: string;
pubkey: string;
created_at: number;
[key: string]: unknown;
}>;
sourceEventId?: string;
[key: string]: unknown;
}>;
patchComments: Array<{
id: string;
content: string;
pubkey: string;
created_at: number;
[key: string]: unknown;
}>;
discussions: Array<{
type: 'thread' | 'comments';
id: string;
title: string;
content: string;
author: string;
createdAt: number;
kind?: number;
pubkey?: string;
comments?: Array<{
id: string;
content: string;
author: string;
createdAt: number;
kind?: number;
pubkey?: string;
npub?: string;
authorName?: string;
authorEmail?: string;
timestamp?: number;
eventId?: string;
};
replies?: Array<{
id: string;
content: string;
author: string;
createdAt: number;
kind?: number;
pubkey?: string;
replies?: Array<{
id: string;
content: string;
author: string;
createdAt: number;
kind?: number;
pubkey?: string;
}>;
}>;
}>;
}>;
releases: Array<{
id: string;
tagName: string;
tagHash?: string;
releaseNotes?: string;
isDraft?: boolean;
isPrerelease?: boolean;
created_at: number;
pubkey: string;
}>;
loadingCommits: boolean;
selectedCommit: string | null;
showDiff: boolean;
diffData: Array<{ file: string; additions: number; deletions: number; diff: string }>;
verifyingCommits: Set<string>;
// Tags
tags: Array<{ name: string; hash: string; message?: string; date?: number }>;
selectedTag: string | null;
showCreateTagDialog: boolean;
newTagName: string;
newTagMessage: string;
newTagRef: string;
// Status updates
statusUpdates: StatusUpdates;
// Selected items
selected: SelectedItems;
// Dialog state
openDialog: DialogType;
// Creating flags (consolidated)
creating: {
patch: boolean;
thread: boolean;
reply: boolean;
release: boolean;
patchHighlight: boolean;
patchComment: boolean;
announcement: boolean;
};
// User state
user: {
pubkey: string | null;
pubkeyHex: string | null;
};
// UI state
ui: {
activeTab: 'files' | 'history' | 'tags' | 'issues' | 'prs' | 'docs' | 'discussions' | 'patches' | 'releases' | 'code-search';
showRepoMenu: boolean;
showFileListOnMobile: boolean;
showLeftPanelOnMobile: boolean;
wordWrap: boolean;
expandedThreads: Set<string>;
};
// Maintainer state
isMaintainer: boolean;
loadingMaintainerStatus: boolean;
allMaintainers: Array<{ pubkey: string; isOwner: boolean }>;
loadingMaintainers: boolean;
maintainersLoaded: boolean;
maintainers: {
isMaintainer: boolean;
all: Array<{ pubkey: string; isOwner: boolean }>;
loaded: boolean;
effectRan: boolean;
lastRepoKey: string | null;
};
// Clone state
isRepoCloned: boolean | null;
checkingCloneStatus: boolean;
cloning: boolean;
copyingCloneUrl: boolean;
apiFallbackAvailable: boolean | null;
clone: {
isCloned: boolean | null;
checking: boolean;
cloning: boolean;
copyingUrl: boolean;
apiFallbackAvailable: boolean | null;
urlsExpanded: boolean;
showAllUrls: boolean;
reachability: Map<string, { reachable: boolean; error?: string; checkedAt: number; serverType: 'git' | 'grasp' | 'unknown' }>;
checkingReachability: Set<string>;
};
// Verification
verification: {
status: {
verified: boolean;
error?: string;
message?: string;
cloneVerifications?: Array<{ url: string; verified: boolean; ownerPubkey: string | null; error?: string }>;
} | null;
fileContent: string | null;
selectedCloneUrl: string | null;
};
// Documentation
docs: {
content: string | null;
html: string | null;
kind: number | null;
};
// Editor state
wordWrap: boolean;
// Code search
codeSearch: {
query: string;
results: Array<{
file: string;
line: number;
content: string;
branch?: string;
repo?: string;
}>;
scope: 'repo' | 'all';
};
// Fork/Bookmark
fork: {
info: { isFork: boolean; originalRepo: { npub: string; repo: string } | null } | null;
forking: boolean;
};
bookmark: {
isBookmarked: boolean;
};
// Repo metadata
metadata: {
address: string | null;
image: string | null;
banner: string | null;
ownerPubkey: string | null;
readmeAutoLoadAttempted: boolean;
};
// Discussion state
discussion: {
replyingToThread: { id: string; kind?: number; pubkey?: string; author: string } | null;
replyingToComment: { id: string; kind?: number; pubkey?: string; author: string } | null;
events: Map<string, NostrEvent>;
nostrLinkEvents: Map<string, NostrEvent>;
nostrLinkProfiles: Map<string, string>; // npub -> pubkey hex
};
// Patch editor
patchEditor: any; // CodeEditor component instance
// Operations
saving: boolean;
// Component lifecycle
isMounted: boolean;
@ -106,57 +471,180 @@ export interface RepoState { @@ -106,57 +471,180 @@ export interface RepoState {
export function createRepoState(): RepoState {
return {
loading: true,
pageData: {},
npub: '',
repo: '',
loading: {
main: true,
readme: false,
commits: false,
issues: false,
issueReplies: false,
prs: false,
patches: false,
patchHighlights: false,
docs: false,
discussions: false,
releases: false,
codeSearch: false,
bookmark: false,
maintainerStatus: false,
maintainers: false,
reachability: false,
verification: false,
repoNotFound: false
},
error: null,
repoNotFound: false,
files: [],
currentPath: '',
currentFile: null,
fileContent: '',
fileLanguage: 'text',
editedContent: '',
hasChanges: false,
files: {
list: [],
currentPath: '',
currentFile: null,
content: '',
language: 'text',
editedContent: '',
hasChanges: false,
pathStack: []
},
preview: {
readme: {
content: null,
path: null,
isMarkdown: false,
html: ''
},
file: {
highlightedContent: '',
html: '',
showPreview: true,
isImage: false,
imageUrl: null
},
copying: false
},
git: {
branches: [],
currentBranch: null,
defaultBranch: null,
commits: [],
selectedCommit: null,
showDiff: false,
diffData: [],
verifyingCommits: new Set(),
tags: [],
selectedTag: null
},
forms: {
file: { fileName: '', content: '' },
branch: { name: '', from: null, defaultName: 'master' },
tag: { name: '', message: '', ref: 'HEAD' },
issue: { subject: '', content: '', labels: [''] },
pr: { subject: '', content: '', commitId: '', branchName: '', labels: [''] },
patch: { content: '', subject: '' },
release: { tagName: '', tagHash: '', notes: '', isDraft: false, isPrerelease: false },
discussion: { threadTitle: '', threadContent: '', replyContent: '' },
patchHighlight: { text: '', startLine: 0, endLine: 0, startPos: 0, endPos: 0, comment: '' },
patchComment: { content: '', replyingTo: null },
commit: { message: '' }
},
issues: [],
issueReplies: [],
prs: [],
patches: [],
patchHighlights: [],
patchComments: [],
discussions: [],
releases: [],
statusUpdates: {
issue: {},
patch: {}
},
selected: {
commit: null,
tag: null,
issue: null,
pr: null,
patch: null,
discussion: null
},
openDialog: null,
creating: {
patch: false,
thread: false,
reply: false,
release: false,
patchHighlight: false,
patchComment: false,
announcement: false
},
user: {
pubkey: null,
pubkeyHex: null
},
ui: {
activeTab: 'files',
showRepoMenu: false,
showFileListOnMobile: true,
showLeftPanelOnMobile: true,
wordWrap: false,
expandedThreads: new Set()
},
maintainers: {
isMaintainer: false,
all: [],
loaded: false,
effectRan: false,
lastRepoKey: null
},
clone: {
isCloned: null,
checking: false,
cloning: false,
copyingUrl: false,
apiFallbackAvailable: null,
urlsExpanded: false,
showAllUrls: false,
reachability: new Map(),
checkingReachability: new Set()
},
verification: {
status: null,
fileContent: null,
selectedCloneUrl: null
},
docs: {
content: null,
html: null,
kind: null
},
codeSearch: {
query: '',
results: [],
scope: 'repo'
},
fork: {
info: null,
forking: false
},
bookmark: {
isBookmarked: false
},
metadata: {
address: null,
image: null,
banner: null,
ownerPubkey: null,
readmeAutoLoadAttempted: false
},
discussion: {
replyingToThread: null,
replyingToComment: null,
events: new Map(),
nostrLinkEvents: new Map(),
nostrLinkProfiles: new Map()
},
patchEditor: null,
saving: false,
branches: [],
currentBranch: null,
defaultBranch: null,
commitMessage: '',
showCommitDialog: false,
userPubkey: null,
userPubkeyHex: null,
activeTab: 'files',
showRepoMenu: false,
pathStack: [],
showCreateFileDialog: false,
newFileName: '',
newFileContent: '',
showCreateBranchDialog: false,
newBranchName: '',
newBranchFrom: null,
defaultBranchName: 'master',
commits: [],
loadingCommits: false,
selectedCommit: null,
showDiff: false,
diffData: [],
verifyingCommits: new Set(),
tags: [],
selectedTag: null,
showCreateTagDialog: false,
newTagName: '',
newTagMessage: '',
newTagRef: 'HEAD',
isMaintainer: false,
loadingMaintainerStatus: false,
allMaintainers: [],
loadingMaintainers: false,
maintainersLoaded: false,
isRepoCloned: null,
checkingCloneStatus: false,
cloning: false,
copyingCloneUrl: false,
apiFallbackAvailable: null,
wordWrap: false,
isMounted: true
};
}

Loading…
Cancel
Save