@ -138,6 +138,10 @@
let checkingCloneStatus = $state(false);
let checkingCloneStatus = $state(false);
let cloning = $state(false);
let cloning = $state(false);
// Helper: Check if repo needs to be cloned for write operations
const needsClone = $derived(isRepoCloned === false);
const cloneTooltip = 'Please clone this repo to use this feature.';
// Verification status
// Verification status
let verificationStatus = $state< { verified : boolean ; error? : string ; message? : string } | null>(null);
let verificationStatus = $state< { verified : boolean ; error? : string ; message? : string } | null>(null);
let showVerificationDialog = $state(false);
let showVerificationDialog = $state(false);
@ -1292,10 +1296,8 @@
await checkMaintainerStatus();
await checkMaintainerStatus();
await loadBookmarkStatus();
await loadBookmarkStatus();
// Check clone status if user has unlimited access
// Check clone status (needed to disable write operations)
if (hasUnlimitedAccess($userStore.userLevel)) {
await checkCloneStatus();
await checkCloneStatus();
}
await checkVerification();
await checkVerification();
await loadReadme();
await loadReadme();
await loadForkInfo();
await loadForkInfo();
@ -1766,8 +1768,9 @@
});
});
if (!response.ok) {
if (!response.ok) {
const errorData = await response.json();
const errorData = await response.json().catch(() => ({ message : response.statusText } ));
throw new Error(errorData.message || 'Failed to save file');
const errorMessage = errorData.message || errorData.error || 'Failed to save file';
throw new Error(errorMessage);
}
}
// Reload file to get updated content
// Reload file to get updated content
@ -2400,10 +2403,15 @@
< / button >
< / button >
{ /if }
{ /if }
{ #if isMaintainer }
{ #if isMaintainer }
< button onclick = {() => {
< button
if (!userPubkey || !isMaintainer) return;
onclick={() => {
showCreateBranchDialog = true;
if (!userPubkey || !isMaintainer || needsClone) return;
}} class="create-branch-button">+ New Branch< / button >
showCreateBranchDialog = true;
}}
class="create-branch-button"
disabled={ needsClone }
title={ needsClone ? cloneTooltip : 'Create a new branch' }
>+ New Branch< / button >
{ /if }
{ /if }
{ /if }
{ /if }
< / div >
< / div >
@ -2503,10 +2511,15 @@
< button onclick = { handleBack } class="back-button" > ← Back</ button >
< button onclick = { handleBack } class="back-button" > ← Back</ button >
{ /if }
{ /if }
{ #if userPubkey && isMaintainer }
{ #if userPubkey && isMaintainer }
< button onclick = {() => {
< button
if (!userPubkey || !isMaintainer) return;
onclick={() => {
showCreateFileDialog = true;
if (!userPubkey || !isMaintainer || needsClone) return;
}} class="create-file-button">+ New File< / button >
showCreateFileDialog = true;
}}
class="create-file-button"
disabled={ needsClone }
title={ needsClone ? cloneTooltip : 'Create a new file' }
>+ New File< / button >
{ /if }
{ /if }
< button
< button
onclick={() => showFileListOnMobile = ! showFileListOnMobile }
onclick={() => showFileListOnMobile = ! showFileListOnMobile }
@ -2539,7 +2552,15 @@
{ /if }
{ /if }
< / button >
< / button >
{ #if userPubkey && isMaintainer && file . type === 'file' }
{ #if userPubkey && isMaintainer && file . type === 'file' }
< button onclick = {() => deleteFile ( file . path )} class="delete-file-button" title = "Delete file" >
< button
onclick={() => {
if (needsClone) return;
deleteFile(file.path);
}}
class="delete-file-button"
disabled={ needsClone }
title={ needsClone ? cloneTooltip : 'Delete file' }
>
< img src = "/icons/x.svg" alt = "Delete" class = "icon-small" / >
< img src = "/icons/x.svg" alt = "Delete" class = "icon-small" / >
< / button >
< / button >
{ /if }
{ /if }
@ -2589,10 +2610,15 @@
< div class = "tags-header" >
< div class = "tags-header" >
< h2 > Tags< / h2 >
< h2 > Tags< / h2 >
{ #if userPubkey && isMaintainer }
{ #if userPubkey && isMaintainer }
< button onclick = {() => {
< button
if (!userPubkey || !isMaintainer) return;
onclick={() => {
showCreateTagDialog = true;
if (!userPubkey || !isMaintainer || needsClone) return;
}} class="create-tag-button">+ New Tag< / button >
showCreateTagDialog = true;
}}
class="create-tag-button"
disabled={ needsClone }
title={ needsClone ? cloneTooltip : 'Create a new tag' }
>+ New Tag< / button >
{ /if }
{ /if }
< / div >
< / div >
{ #if tags . length === 0 }
{ #if tags . length === 0 }
@ -2739,10 +2765,15 @@
< span class = "unsaved-indicator" > ● Unsaved changes< / span >
< span class = "unsaved-indicator" > ● Unsaved changes< / span >
{ /if }
{ /if }
{ #if isMaintainer }
{ #if isMaintainer }
< button onclick = {() => {
< button
if (!userPubkey || !isMaintainer) return;
onclick={() => {
showCommitDialog = true;
if (!userPubkey || !isMaintainer || needsClone) return;
}} disabled={ ! hasChanges || saving } class="save-button">
showCommitDialog = true;
}}
disabled={ ! hasChanges || saving || needsClone }
class="save-button"
title={ needsClone ? cloneTooltip : ( hasChanges ? 'Save changes' : 'No changes to save' )}
>
{ saving ? 'Saving...' : 'Save' }
{ saving ? 'Saving...' : 'Save' }
< / button >
< / button >
{ :else if userPubkey }
{ :else if userPubkey }
@ -2771,6 +2802,7 @@
content={ editedContent }
content={ editedContent }
language={ fileLanguage }
language={ fileLanguage }
onChange={ handleContentChange }
onChange={ handleContentChange }
readOnly={ needsClone }
/>
/>
{ : else }
{ : else }
< div class = "read-only-editor" >
< div class = "read-only-editor" >
@ -3207,7 +3239,12 @@
< / label >
< / label >
< div class = "modal-actions" >
< div class = "modal-actions" >
< button onclick = {() => showCreateFileDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = {() => showCreateFileDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = { createFile } disabled= { ! newFileName . trim () || saving } class = "save-button" >
< button
onclick={ createFile }
disabled={ ! newFileName . trim () || saving || needsClone }
class="save-button"
title={ needsClone ? cloneTooltip : '' }
>
{ saving ? 'Creating...' : 'Create' }
{ saving ? 'Creating...' : 'Create' }
< / button >
< / button >
< / div >
< / div >
@ -3249,7 +3286,12 @@
< / label >
< / label >
< div class = "modal-actions" >
< div class = "modal-actions" >
< button onclick = {() => showCreateBranchDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = {() => showCreateBranchDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = { createBranch } disabled= { ! newBranchName . trim () || saving } class = "save-button" >
< button
onclick={ createBranch }
disabled={ ! newBranchName . trim () || saving || needsClone }
class="save-button"
title={ needsClone ? cloneTooltip : '' }
>
{ saving ? 'Creating...' : 'Create Branch' }
{ saving ? 'Creating...' : 'Create Branch' }
< / button >
< / button >
< / div >
< / div >
@ -3290,7 +3332,12 @@
< / label >
< / label >
< div class = "modal-actions" >
< div class = "modal-actions" >
< button onclick = {() => showCreateTagDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = {() => showCreateTagDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = { createTag } disabled= { ! newTagName . trim () || saving } class = "save-button" >
< button
onclick={ createTag }
disabled={ ! newTagName . trim () || saving || needsClone }
class="save-button"
title={ needsClone ? cloneTooltip : '' }
>
{ saving ? 'Creating...' : 'Create Tag' }
{ saving ? 'Creating...' : 'Create Tag' }
< / button >
< / button >
< / div >
< / div >
@ -3506,7 +3553,12 @@
< / label >
< / label >
< div class = "modal-actions" >
< div class = "modal-actions" >
< button onclick = {() => showCommitDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = {() => showCommitDialog = false } class="cancel-button" > Cancel</ button >
< button onclick = { saveFile } disabled= { ! commitMessage . trim () || saving } class = "save-button" >
< button
onclick={ saveFile }
disabled={ ! commitMessage . trim () || saving || needsClone }
class="save-button"
title={ needsClone ? cloneTooltip : '' }
>
{ saving ? 'Saving...' : 'Commit & Save' }
{ saving ? 'Saving...' : 'Commit & Save' }
< / button >
< / button >
< / div >
< / div >