mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-10 22:14:48 +02:00
Update logs to mask server address, add share txt file button
This commit is contained in:
parent
390388fe83
commit
2000534e37
3 changed files with 78 additions and 16 deletions
|
@ -1,52 +1,110 @@
|
|||
<template>
|
||||
<div class="w-full h-full p-4">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center mb-2 space-x-2">
|
||||
<p class="text-lg font-bold">{{ $strings.ButtonLogs }}</p>
|
||||
<ui-icon-btn outlined borderless icon="content_copy" @click="copyToClipboard" />
|
||||
<ui-icon-btn outlined borderless :icon="isCopied ? 'check' : 'content_copy'" @click="copyToClipboard" />
|
||||
<ui-icon-btn outlined borderless icon="share" @click="shareLogs" />
|
||||
<div class="flex-grow"></div>
|
||||
<ui-btn class="h-9" :padding-y="1" :padding-x="4" @click="toggleMaskServerAddress">
|
||||
{{ maskServerAddress ? $strings.ButtonUnmaskServerAddress : $strings.ButtonMaskServerAddress }}
|
||||
</ui-btn>
|
||||
</div>
|
||||
<div class="w-full h-[calc(100%-40px)] overflow-y-auto relative" ref="logContainer">
|
||||
<div v-if="hasScrolled" class="sticky top-0 left-0 w-full h-10 bg-gradient-to-t from-transparent to-bg z-10 pointer-events-none"></div>
|
||||
|
||||
<div v-for="log in logs" :key="log.id" class="py-1">
|
||||
<div class="flex items-center space-x-4 mb-1">
|
||||
<div class="text-xs uppercase font-bold" :class="{ 'text-error': log.level === 'error', 'text-blue-600': log.level === 'info' }">{{ log.level }}</div>
|
||||
<div class="text-xs text-gray-400">{{ new Date(log.timestamp).toLocaleString() }}</div>
|
||||
<div class="text-xs uppercase font-bold" :class="{ 'text-error': log.level === 'error', 'text-blue-500': log.level === 'info' }">{{ log.level }}</div>
|
||||
<div class="text-xs text-gray-400">{{ formatEpochToDatetimeString(log.timestamp) }}</div>
|
||||
</div>
|
||||
<div class="text-xs">{{ log.message }}</div>
|
||||
<div class="text-xs">{{ maskServerAddress ? log.maskedMessage : log.message }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { AbsLogger } from '@/plugins/capacitor'
|
||||
import { FileSharer } from '@webnativellc/capacitor-filesharer'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
logs: [],
|
||||
hasScrolled: false
|
||||
isCopied: false,
|
||||
hasScrolled: false,
|
||||
maskServerAddress: true
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
toggleMaskServerAddress() {
|
||||
this.maskServerAddress = !this.maskServerAddress
|
||||
},
|
||||
copyToClipboard() {
|
||||
this.$copyToClipboard(
|
||||
this.logs
|
||||
this.$copyToClipboard(this.getLogsString()).then(() => {
|
||||
this.isCopied = true
|
||||
setTimeout(() => {
|
||||
this.isCopied = false
|
||||
}, 2000)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Formats an epoch timestamp to YYYY-MM-DD HH:mm:ss.SSS
|
||||
* Use 24 hour time format
|
||||
* @param {number} epoch
|
||||
* @returns {string}
|
||||
*/
|
||||
formatEpochToDatetimeString(epoch) {
|
||||
return new Date(epoch)
|
||||
.toLocaleString('en-US', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
fractionalSecondDigits: 3,
|
||||
hour12: false
|
||||
})
|
||||
.replace(',', '')
|
||||
},
|
||||
getLogsString() {
|
||||
return this.logs
|
||||
.map((log) => {
|
||||
return `${log.timestamp} [${log.level}] ${log.message}`
|
||||
const logMessage = this.maskServerAddress ? log.maskedMessage : log.message
|
||||
return `${this.formatEpochToDatetimeString(log.timestamp)} [${log.level.toUpperCase()}] ${logMessage}`
|
||||
})
|
||||
.join('\n')
|
||||
)
|
||||
},
|
||||
shareLogs() {
|
||||
// Share .txt file with logs
|
||||
const base64Data = Buffer.from(this.getLogsString()).toString('base64')
|
||||
|
||||
FileSharer.share({
|
||||
filename: `audiobookshelf_logs.txt`,
|
||||
contentType: 'text/plain',
|
||||
base64Data
|
||||
}).catch((error) => {
|
||||
if (error.message !== 'USER_CANCELLED') {
|
||||
console.error('Failed to share', error.message)
|
||||
this.$toast.error('Failed to share: ' + error.message)
|
||||
}
|
||||
})
|
||||
},
|
||||
scrollToBottom() {
|
||||
this.$refs.logContainer.scrollTop = this.$refs.logContainer.scrollHeight
|
||||
this.hasScrolled = this.$refs.logContainer.scrollTop > 0
|
||||
},
|
||||
maskLogMessage(message) {
|
||||
return message.replace(/(https?:\/\/)\S+/g, '$1[SERVER_ADDRESS]')
|
||||
},
|
||||
loadLogs() {
|
||||
AbsLogger.getAllLogs().then((logData) => {
|
||||
const logs = logData.value || []
|
||||
this.logs = logs
|
||||
this.logs = logs.map((log) => {
|
||||
log.maskedMessage = this.maskLogMessage(log.message)
|
||||
return log
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
|
|
|
@ -31,7 +31,9 @@ class AbsLoggerWeb extends WebPlugin {
|
|||
}
|
||||
|
||||
async getAllLogs() {
|
||||
return this.logs
|
||||
return {
|
||||
value: this.logs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
"ButtonLocalMedia": "Local Media",
|
||||
"ButtonLogs": "Logs",
|
||||
"ButtonManageLocalFiles": "Manage Local Files",
|
||||
"ButtonMaskServerAddress": "Mask server address",
|
||||
"ButtonNewFolder": "New Folder",
|
||||
"ButtonNextEpisode": "Next Episode",
|
||||
"ButtonOk": "Ok",
|
||||
|
@ -51,6 +52,7 @@
|
|||
"ButtonStream": "Stream",
|
||||
"ButtonSubmit": "Submit",
|
||||
"ButtonSwitchServerUser": "Switch Server/User",
|
||||
"ButtonUnmaskServerAddress": "Unmask server address",
|
||||
"ButtonUserStats": "User Stats",
|
||||
"ButtonYes": "Yes",
|
||||
"HeaderAccount": "Account",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue