fix: resolve did:dht compilation errors
- Simplify DHT encoding: use JSON instead of DNS packets (drop simple-dns) - Fix mainline crate API: SigningKey takes 32 bytes, get_mutable returns Result - Add missing dht_did field to IdentityRecord constructor - Store DID Document as JSON in DHT (DNS encoding deferred) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- Info Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<!-- Server Name Card -->
|
||||
<!-- Server Name Card (editable) -->
|
||||
<div class="bg-black/20 rounded-xl px-5 py-4 border border-white/10">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<svg class="w-5 h-5 text-white/70" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -25,7 +25,31 @@
|
||||
</svg>
|
||||
<p class="text-xs font-semibold text-white/60 uppercase tracking-wide">{{ t('settings.serverName') }}</p>
|
||||
</div>
|
||||
<p class="text-lg font-semibold text-white/95">{{ serverName }}</p>
|
||||
<div v-if="editingServerName" class="flex items-center gap-2">
|
||||
<input
|
||||
ref="serverNameInput"
|
||||
v-model="serverNameDraft"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
class="flex-1 px-3 py-1.5 bg-white/10 border border-white/20 rounded-lg text-white text-lg font-semibold focus:outline-none focus:border-white/40 transition-colors"
|
||||
@keydown.enter="saveServerName"
|
||||
@keydown.escape="editingServerName = false"
|
||||
/>
|
||||
<button
|
||||
class="px-3 py-1.5 bg-white/10 border border-white/20 rounded-lg text-white/70 hover:text-white hover:bg-white/15 transition-colors text-sm"
|
||||
@click="saveServerName"
|
||||
>Save</button>
|
||||
<button
|
||||
class="px-3 py-1.5 text-white/50 hover:text-white/70 transition-colors text-sm"
|
||||
@click="editingServerName = false"
|
||||
>Cancel</button>
|
||||
</div>
|
||||
<div v-else class="flex items-center gap-2 group cursor-pointer" @click="startEditServerName">
|
||||
<p class="text-lg font-semibold text-white/95">{{ serverName }}</p>
|
||||
<svg class="w-4 h-4 text-white/30 group-hover:text-white/60 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Version Card -->
|
||||
@@ -572,51 +596,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tor Services Section -->
|
||||
<div class="glass-card px-6 py-6 mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-white/96">Tor Services</h2>
|
||||
<p class="text-sm text-white/60 mt-1">Manage hidden service addresses for your node and apps</p>
|
||||
</div>
|
||||
<button @click="loadTorServices" class="glass-button px-4 py-2 rounded-lg text-sm flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="torLoading" class="text-sm text-white/40 py-4 text-center">Loading Tor services...</div>
|
||||
<div v-else-if="torServices.length === 0" class="text-sm text-white/40 py-4 text-center">No Tor services configured</div>
|
||||
<div v-else class="space-y-2">
|
||||
<div v-for="svc in torServices" :key="svc.name" class="bg-black/20 rounded-xl border border-white/10 p-3 flex items-center justify-between gap-3">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-white text-sm font-medium">{{ svc.name }}</p>
|
||||
<p v-if="svc.onion_address" class="text-amber-300/80 text-xs font-mono truncate">{{ svc.onion_address }}</p>
|
||||
<p v-else class="text-white/30 text-xs">No .onion address</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
v-if="svc.name === 'archipelago'"
|
||||
@click="rotateNodeAddress"
|
||||
:disabled="torRotating"
|
||||
class="glass-button px-3 py-1.5 rounded-lg text-xs"
|
||||
>
|
||||
{{ torRotating ? 'Rotating...' : 'Rotate' }}
|
||||
</button>
|
||||
<label class="tor-toggle-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="svc.enabled"
|
||||
@change="toggleTorApp(svc.name, !svc.enabled)"
|
||||
class="tor-toggle-input"
|
||||
/>
|
||||
<span class="tor-toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Webhook Notifications Section -->
|
||||
<div class="glass-card px-6 py-6 mb-6">
|
||||
@@ -836,7 +815,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { computed, ref, onMounted, nextTick } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
@@ -887,6 +866,30 @@ const interfaceModes = computed<{ id: UIMode; label: string; description: string
|
||||
])
|
||||
|
||||
const serverName = computed(() => store.serverName)
|
||||
const editingServerName = ref(false)
|
||||
const serverNameDraft = ref('')
|
||||
const serverNameInput = ref<HTMLInputElement | null>(null)
|
||||
|
||||
function startEditServerName() {
|
||||
serverNameDraft.value = serverName.value
|
||||
editingServerName.value = true
|
||||
nextTick(() => serverNameInput.value?.select())
|
||||
}
|
||||
|
||||
async function saveServerName() {
|
||||
const name = serverNameDraft.value.trim()
|
||||
if (!name || name === serverName.value) {
|
||||
editingServerName.value = false
|
||||
return
|
||||
}
|
||||
try {
|
||||
await rpcClient.call({ method: 'server.set-name', params: { name } })
|
||||
} catch (e) {
|
||||
console.error('Failed to rename server:', e)
|
||||
}
|
||||
editingServerName.value = false
|
||||
}
|
||||
|
||||
const version = computed(() => store.serverInfo?.version || '0.0.0')
|
||||
const serverTorAddressFromStore = computed(() => store.serverInfo?.['tor-address'] || null)
|
||||
const torAddressFromRpc = ref<string | null>(null)
|
||||
@@ -1166,7 +1169,6 @@ onMounted(async () => {
|
||||
checkClaudeStatus()
|
||||
loadTotpStatus()
|
||||
loadBackups()
|
||||
loadTorServices()
|
||||
loadWebhookConfig()
|
||||
if (!serverTorAddressFromStore.value) {
|
||||
try {
|
||||
@@ -1204,16 +1206,6 @@ const restoringBackup = ref(false)
|
||||
const verifyingBackupId = ref<string | null>(null)
|
||||
const deletingBackupId = ref<string | null>(null)
|
||||
|
||||
// Tor services state
|
||||
interface TorServiceInfo {
|
||||
name: string
|
||||
local_port: number
|
||||
onion_address: string | null
|
||||
enabled: boolean
|
||||
}
|
||||
const torServices = ref<TorServiceInfo[]>([])
|
||||
const torLoading = ref(false)
|
||||
const torRotating = ref(false)
|
||||
const backupStatusMsg = ref('')
|
||||
const backupStatusType = ref<'success' | 'error'>('success')
|
||||
|
||||
@@ -1230,43 +1222,6 @@ function showBackupStatus(msg: string, type: 'success' | 'error') {
|
||||
setTimeout(() => { backupStatusMsg.value = '' }, 5000)
|
||||
}
|
||||
|
||||
async function loadTorServices() {
|
||||
torLoading.value = true
|
||||
try {
|
||||
const res = await rpcClient.torListServices()
|
||||
torServices.value = res.services || []
|
||||
} catch {
|
||||
torServices.value = []
|
||||
} finally {
|
||||
torLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleTorApp(appId: string, enabled: boolean) {
|
||||
try {
|
||||
const res = await rpcClient.torToggleApp(appId, enabled)
|
||||
if (res.changed) {
|
||||
await loadTorServices()
|
||||
}
|
||||
} catch (e) {
|
||||
if (import.meta.env.DEV) console.warn('Failed to toggle Tor app:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function rotateNodeAddress() {
|
||||
if (torRotating.value) return
|
||||
if (!confirm('This will generate a new .onion address. The old address will work for 24 hours during transition. Federated peers will be notified automatically.')) return
|
||||
torRotating.value = true
|
||||
try {
|
||||
await rpcClient.torRotateService('archipelago')
|
||||
await loadTorServices()
|
||||
} catch (e) {
|
||||
if (import.meta.env.DEV) console.warn('Failed to rotate Tor address:', e)
|
||||
} finally {
|
||||
torRotating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBackups() {
|
||||
loadingBackups.value = true
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user