Huge refactor, submission system addition & security improvements. +Implementation of moderation cmds.
This commit is contained in:
92
frontend/src/components/CodeViewer.svelte
Normal file
92
frontend/src/components/CodeViewer.svelte
Normal file
@@ -0,0 +1,92 @@
|
||||
<script>
|
||||
import { detectLanguage } from '../lib/lang.js'
|
||||
import hljs from 'highlight.js'
|
||||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
|
||||
let { src, rawUrl = '', fileName = '' } = $props()
|
||||
let text = $state('')
|
||||
let loading = $state(true)
|
||||
let lang = $derived(detectLanguage(fileName))
|
||||
|
||||
$effect(() => {
|
||||
fetch(src)
|
||||
.then(r => r.text())
|
||||
.then(t => {
|
||||
text = t
|
||||
loading = false
|
||||
if (lang) {
|
||||
requestAnimationFrame(() => {
|
||||
const block = document.querySelector('.code-viewer code')
|
||||
if (block) hljs.highlightElement(block)
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
text = 'Failed to load code content.'
|
||||
loading = false
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="code-viewer">
|
||||
{#if fileName || rawUrl}
|
||||
<div class="header">
|
||||
{#if fileName}<span class="label">{fileName}</span>{/if}
|
||||
{#if rawUrl}<a class="raw-btn" href={rawUrl} target="_blank">[ Raw ]</a>{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if loading}
|
||||
<p>Loading code...</p>
|
||||
{:else}
|
||||
<pre><code class={lang ? `language-${lang}` : ''}>{text}</code></pre>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.code-viewer {
|
||||
max-width: 1000px;
|
||||
margin: 24px auto;
|
||||
padding: 16px;
|
||||
background: var(--retro-panel);
|
||||
border: 3px solid var(--retro-border);
|
||||
box-shadow: 6px 6px 0px var(--retro-shadow);
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid var(--retro-border);
|
||||
}
|
||||
.label {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.6rem;
|
||||
color: var(--retro-green);
|
||||
}
|
||||
.raw-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.5rem;
|
||||
padding: 6px 10px;
|
||||
border: 2px solid var(--retro-border);
|
||||
background: var(--retro-panel);
|
||||
color: var(--retro-fg);
|
||||
text-decoration: none;
|
||||
box-shadow: 2px 2px 0px rgba(0,0,0,0.15);
|
||||
}
|
||||
.raw-btn:hover {
|
||||
background: var(--retro-green);
|
||||
color: #fff;
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
background: #1e1e1e;
|
||||
padding: 12px;
|
||||
border: 2px solid var(--retro-border);
|
||||
}
|
||||
code {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
</style>
|
||||
98
frontend/src/components/DocxViewer.svelte
Normal file
98
frontend/src/components/DocxViewer.svelte
Normal file
@@ -0,0 +1,98 @@
|
||||
<script>
|
||||
let { src, downloadUrl, file } = $props()
|
||||
let html = $state('')
|
||||
let loading = $state(true)
|
||||
let error = $state('')
|
||||
|
||||
$effect(() => {
|
||||
fetch(src)
|
||||
.then(r => r.arrayBuffer())
|
||||
.then(buf => import('mammoth').then(m => m.default.convertToHtml({ arrayBuffer: buf })))
|
||||
.then(result => {
|
||||
html = result.value
|
||||
loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
error = 'Failed to render DOCX.'
|
||||
loading = false
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="docx-viewer">
|
||||
<div class="header">
|
||||
<span class="label">[ DOCX ]</span>
|
||||
<a class="raw-btn" href={downloadUrl} download={file.name}>Download</a>
|
||||
</div>
|
||||
{#if loading}
|
||||
<p>Loading DOCX...</p>
|
||||
{:else if error}
|
||||
<p class="error">{error}</p>
|
||||
<a class="btn" href={downloadUrl} download={file.name}>Download</a>
|
||||
{:else}
|
||||
<div class="docx-content">{@html html}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.docx-viewer {
|
||||
max-width: 900px;
|
||||
margin: 24px auto;
|
||||
padding: 24px;
|
||||
background: var(--retro-panel);
|
||||
border: 3px solid var(--retro-border);
|
||||
box-shadow: 6px 6px 0px var(--retro-shadow);
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid var(--retro-border);
|
||||
}
|
||||
.label {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.6rem;
|
||||
color: var(--retro-green);
|
||||
}
|
||||
.raw-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.5rem;
|
||||
padding: 6px 10px;
|
||||
border: 2px solid var(--retro-border);
|
||||
background: var(--retro-panel);
|
||||
color: var(--retro-fg);
|
||||
text-decoration: none;
|
||||
box-shadow: 2px 2px 0px rgba(0,0,0,0.15);
|
||||
}
|
||||
.raw-btn:hover {
|
||||
background: var(--retro-green);
|
||||
color: #fff;
|
||||
}
|
||||
.docx-content {
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.docx-content :global(p) { margin: 0.8em 0; }
|
||||
.docx-content :global(table) { border-collapse: collapse; width: 100%; }
|
||||
.docx-content :global(td), .docx-content :global(th) { border: 1px solid #ccc; padding: 6px; }
|
||||
.error { color: var(--retro-danger); }
|
||||
.btn {
|
||||
display: inline-block;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.55rem;
|
||||
padding: 10px 14px;
|
||||
border: 3px solid var(--retro-border);
|
||||
background: var(--retro-panel);
|
||||
color: var(--retro-fg);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
box-shadow: 3px 3px 0px rgba(0,0,0,0.15);
|
||||
margin-top: 8px;
|
||||
}
|
||||
.btn:hover {
|
||||
background: var(--retro-green);
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,14 @@
|
||||
<script>
|
||||
let { src, name } = $props()
|
||||
let failed = $state(false)
|
||||
</script>
|
||||
|
||||
<div class="image-viewer">
|
||||
<img {src} alt={name} decoding="async" loading="eager" />
|
||||
{#if failed}
|
||||
<div class="image-error">[ Failed to load image ]</div>
|
||||
{:else}
|
||||
<img {src} alt={name} decoding="async" loading="eager" onerror={() => failed = true} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -19,4 +24,10 @@
|
||||
box-shadow: 6px 6px 0px var(--retro-shadow);
|
||||
image-rendering: auto;
|
||||
}
|
||||
.image-error {
|
||||
color: var(--retro-danger);
|
||||
font-family: var(--retro-font, monospace);
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
<script>
|
||||
import { fileUrl } from '../lib/api.js'
|
||||
import { fileUrl, rawUrl } from '../lib/api.js'
|
||||
import { detectLanguage } from '../lib/lang.js'
|
||||
import ImageViewer from './ImageViewer.svelte'
|
||||
import VideoPlayer from './VideoPlayer.svelte'
|
||||
import AudioPlayer from './AudioPlayer.svelte'
|
||||
import MarkdownRenderer from './MarkdownRenderer.svelte'
|
||||
import TextViewer from './TextViewer.svelte'
|
||||
import CodeViewer from './CodeViewer.svelte'
|
||||
import DocumentCard from './DocumentCard.svelte'
|
||||
import ExecutableWarning from './ExecutableWarning.svelte'
|
||||
import SensitiveWarning from './SensitiveWarning.svelte'
|
||||
import PdfViewer from './PdfViewer.svelte'
|
||||
import DocxViewer from './DocxViewer.svelte'
|
||||
|
||||
let { files, cxid, password = '' } = $props()
|
||||
|
||||
@@ -17,7 +22,11 @@
|
||||
if (flags & 4) return 'audio'
|
||||
if (flags & 8) return 'markdown'
|
||||
if (flags & 16) return 'text'
|
||||
if (flags & 32) {
|
||||
return file.mime === 'application/pdf' ? 'pdf' : 'docx'
|
||||
}
|
||||
if (flags & 64 || flags & 128) return 'dangerous'
|
||||
if (flags & 512) return 'sensitive'
|
||||
return 'document'
|
||||
}
|
||||
</script>
|
||||
@@ -39,9 +48,19 @@
|
||||
{:else if viewer === 'markdown'}
|
||||
<MarkdownRenderer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{:else if viewer === 'text'}
|
||||
<TextViewer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{#if detectLanguage(file.name)}
|
||||
<CodeViewer src={fileUrl(cxid, file.idx, false, password)} rawUrl={rawUrl(cxid, file.idx, password)} fileName={file.name} />
|
||||
{:else}
|
||||
<TextViewer src={fileUrl(cxid, file.idx, false, password)} rawUrl={rawUrl(cxid, file.idx, password)} fileName={file.name} />
|
||||
{/if}
|
||||
{:else if viewer === 'pdf'}
|
||||
<PdfViewer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{:else if viewer === 'docx'}
|
||||
<DocxViewer src={fileUrl(cxid, file.idx, false, password)} downloadUrl={fileUrl(cxid, file.idx, true, password)} {file} />
|
||||
{:else if viewer === 'dangerous'}
|
||||
<ExecutableWarning {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{:else if viewer === 'sensitive'}
|
||||
<SensitiveWarning {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{:else}
|
||||
<DocumentCard {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{/if}
|
||||
|
||||
23
frontend/src/components/PdfViewer.svelte
Normal file
23
frontend/src/components/PdfViewer.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
let { src } = $props()
|
||||
</script>
|
||||
|
||||
<div class="pdf-viewer">
|
||||
<embed src={src} type="application/pdf" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.pdf-viewer {
|
||||
max-width: 1000px;
|
||||
margin: 24px auto;
|
||||
padding: 16px;
|
||||
background: var(--retro-panel);
|
||||
border: 3px solid var(--retro-border);
|
||||
box-shadow: 6px 6px 0px var(--retro-shadow);
|
||||
}
|
||||
embed {
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
border: 2px solid var(--retro-border);
|
||||
}
|
||||
</style>
|
||||
56
frontend/src/components/SensitiveWarning.svelte
Normal file
56
frontend/src/components/SensitiveWarning.svelte
Normal file
@@ -0,0 +1,56 @@
|
||||
<script>
|
||||
import { formatSize } from '../lib/api.js'
|
||||
|
||||
let { file, downloadUrl } = $props()
|
||||
</script>
|
||||
|
||||
<div class="warning-card">
|
||||
<div class="badge">[ Sensitive Data ]</div>
|
||||
<p class="name">{file.name}</p>
|
||||
<p class="meta">{file.mime} • {formatSize(file.size)}</p>
|
||||
<p class="notice">
|
||||
This file may contain sensitive data. Be careful when handling it.
|
||||
</p>
|
||||
<a class="btn" href={downloadUrl} download={file.name}>Download</a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.warning-card {
|
||||
max-width: 600px;
|
||||
margin: 24px auto;
|
||||
padding: 24px;
|
||||
background: #fffdf5;
|
||||
border: 3px solid #c78000;
|
||||
box-shadow: 6px 6px 0px rgba(199,128,0,0.15);
|
||||
text-align: center;
|
||||
}
|
||||
.badge {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.6rem;
|
||||
color: #c78000;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.name {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.7rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
.meta {
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.notice {
|
||||
font-size: 1rem;
|
||||
color: #555;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.btn {
|
||||
border-color: #c78000;
|
||||
color: #c78000;
|
||||
}
|
||||
.btn:hover {
|
||||
background: #c78000;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
let { src } = $props()
|
||||
let { src, rawUrl = '', fileName = '' } = $props()
|
||||
let text = $state('')
|
||||
let loading = $state(true)
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
</script>
|
||||
|
||||
<div class="text-viewer">
|
||||
{#if fileName || rawUrl}
|
||||
<div class="header">
|
||||
{#if fileName}<span class="label">{fileName}</span>{/if}
|
||||
{#if rawUrl}<a class="raw-btn" href={rawUrl} target="_blank">[ Raw ]</a>{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if loading}
|
||||
<p>Loading text...</p>
|
||||
{:else}
|
||||
@@ -34,6 +40,33 @@
|
||||
border: 3px solid var(--retro-border);
|
||||
box-shadow: 6px 6px 0px var(--retro-shadow);
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid var(--retro-border);
|
||||
}
|
||||
.label {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.6rem;
|
||||
color: var(--retro-green);
|
||||
}
|
||||
.raw-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.5rem;
|
||||
padding: 6px 10px;
|
||||
border: 2px solid var(--retro-border);
|
||||
background: var(--retro-panel);
|
||||
color: var(--retro-fg);
|
||||
text-decoration: none;
|
||||
box-shadow: 2px 2px 0px rgba(0,0,0,0.15);
|
||||
}
|
||||
.raw-btn:hover {
|
||||
background: var(--retro-green);
|
||||
color: #fff;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<div class="video-player">
|
||||
<!-- svelte-ignore a11y_media_has_caption -->
|
||||
<video controls preload="metadata" {src}></video>
|
||||
<video controls preload="metadata" {src}>
|
||||
<source src={src} type={mime} />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// "window.location.origin"
|
||||
const API_BASE = "http://127.0.0.1:8090";
|
||||
|
||||
export async function fetchMetadata(cxid) {
|
||||
const res = await fetch(
|
||||
`${API_BASE}/api/content/${encodeURIComponent(cxid)}`,
|
||||
);
|
||||
export async function fetchMetadata(cxid, password = "") {
|
||||
let url = `${API_BASE}/api/content/${encodeURIComponent(cxid)}`;
|
||||
if (password) url += `?sc=${encodeURIComponent(password)}`;
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
const err = new Error(await res.text());
|
||||
err.status = res.status;
|
||||
@@ -34,6 +34,12 @@ export function fileUrl(cxid, fileIdx, download = false, password = "") {
|
||||
return url;
|
||||
}
|
||||
|
||||
export function rawUrl(cxid, fileIdx, password = "") {
|
||||
let url = `${API_BASE}/api/content/${encodeURIComponent(cxid)}/file/${fileIdx}/raw`;
|
||||
if (password) url += `?sc=${encodeURIComponent(password)}`;
|
||||
return url;
|
||||
}
|
||||
|
||||
export function formatSize(bytes) {
|
||||
if (bytes === 0) return "0 B";
|
||||
const units = ["B", "KB", "MB", "GB"];
|
||||
|
||||
16
frontend/src/lib/lang.js
Normal file
16
frontend/src/lib/lang.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const EXT_TO_LANG = {
|
||||
py: 'python', rs: 'rust', js: 'javascript', ts: 'typescript',
|
||||
jsx: 'javascript', tsx: 'typescript', c: 'c', cpp: 'cpp', cc: 'cpp',
|
||||
h: 'c', hpp: 'cpp', go: 'go', java: 'java', kt: 'kotlin',
|
||||
swift: 'swift', rb: 'ruby', php: 'php', cs: 'csharp', scala: 'scala',
|
||||
r: 'r', m: 'objectivec', mm: 'objectivec', pl: 'perl', lua: 'lua',
|
||||
json: 'json', xml: 'xml', yaml: 'yaml', yml: 'yaml', toml: 'toml',
|
||||
ini: 'ini', cfg: 'ini', sh: 'bash', bash: 'bash', ps1: 'powershell',
|
||||
bat: 'batch', cmd: 'batch', sql: 'sql', dockerfile: 'dockerfile',
|
||||
makefile: 'makefile', cmake: 'cmake',
|
||||
};
|
||||
|
||||
export function detectLanguage(fileName) {
|
||||
const ext = fileName.split('.').pop()?.toLowerCase();
|
||||
return ext ? (EXT_TO_LANG[ext] || null) : null;
|
||||
}
|
||||
@@ -64,6 +64,13 @@
|
||||
<button onclick={submit} disabled={loading}>
|
||||
{loading ? 'Loading...' : '[ Unlock ]'}
|
||||
</button>
|
||||
|
||||
<details class="misc-section">
|
||||
<summary>[ Misc ]</summary>
|
||||
<div class="misc-content">
|
||||
<a href="https://t.me/harmfulmeowbot?start=report" target="_blank" rel="noopener">Report Content</a>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
@@ -135,4 +142,31 @@
|
||||
margin-top: 12px;
|
||||
color: #777;
|
||||
}
|
||||
.misc-section {
|
||||
margin-top: 8px;
|
||||
border: 2px solid var(--retro-border);
|
||||
padding: 8px 12px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.misc-section summary {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 0.55rem;
|
||||
color: var(--retro-green);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.misc-content {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
.misc-content a {
|
||||
font-size: 0.9rem;
|
||||
color: var(--retro-green);
|
||||
text-decoration: none;
|
||||
}
|
||||
.misc-content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
<script>
|
||||
import { fetchMetadata, verifyPassword, fileUrl } from '../lib/api.js'
|
||||
import { fetchMetadata, verifyPassword, fileUrl, rawUrl } from '../lib/api.js'
|
||||
import { detectLanguage } from '../lib/lang.js'
|
||||
import ImageViewer from '../components/ImageViewer.svelte'
|
||||
import VideoPlayer from '../components/VideoPlayer.svelte'
|
||||
import AudioPlayer from '../components/AudioPlayer.svelte'
|
||||
import MarkdownRenderer from '../components/MarkdownRenderer.svelte'
|
||||
import TextViewer from '../components/TextViewer.svelte'
|
||||
import CodeViewer from '../components/CodeViewer.svelte'
|
||||
import DocumentCard from '../components/DocumentCard.svelte'
|
||||
import ExecutableWarning from '../components/ExecutableWarning.svelte'
|
||||
import SensitiveWarning from '../components/SensitiveWarning.svelte'
|
||||
import PdfViewer from '../components/PdfViewer.svelte'
|
||||
import DocxViewer from '../components/DocxViewer.svelte'
|
||||
import MixedGallery from '../components/MixedGallery.svelte'
|
||||
|
||||
let { cxid, sc } = $props()
|
||||
@@ -28,28 +33,18 @@
|
||||
phase = 'loading_meta'
|
||||
error = ''
|
||||
try {
|
||||
const meta = await fetchMetadata(cxid)
|
||||
const meta = await fetchMetadata(cxid, password)
|
||||
metadata = meta
|
||||
if (meta.has_password && !password) {
|
||||
phase = 'rendering'
|
||||
} catch (e) {
|
||||
const status = e.status || 0
|
||||
if (status === 401) {
|
||||
phase = 'password_required'
|
||||
return
|
||||
}
|
||||
if (meta.has_password) {
|
||||
const ok = await verifyPassword(cxid, password)
|
||||
if (!ok) {
|
||||
phase = 'password_required'
|
||||
error = 'Incorrect password.'
|
||||
return
|
||||
}
|
||||
}
|
||||
phase = 'rendering'
|
||||
} catch (e) {
|
||||
phase = 'error'
|
||||
const status = e.status || 0
|
||||
if (status === 404) {
|
||||
error = '[ Not Found ] This content does not exist or has been removed.'
|
||||
} else if (status === 401) {
|
||||
error = '[ Unauthorized ] This content requires a password.'
|
||||
} else if (status === 429) {
|
||||
error = '[ Rate Limited ] Too many requests. Please wait.'
|
||||
} else if (status >= 500) {
|
||||
@@ -65,6 +60,7 @@
|
||||
if (!password) return
|
||||
const ok = await verifyPassword(cxid, password)
|
||||
if (ok) {
|
||||
metadata = await fetchMetadata(cxid, password)
|
||||
phase = 'rendering'
|
||||
} else {
|
||||
error = 'Incorrect password.'
|
||||
@@ -83,8 +79,12 @@
|
||||
if (flags & 4) return 'audio'
|
||||
if (flags & 8) return 'markdown'
|
||||
if (flags & 16) return 'text'
|
||||
if (flags & 32) {
|
||||
return file.mime === 'application/pdf' ? 'pdf' : 'docx'
|
||||
}
|
||||
if (flags & 64) return 'executable'
|
||||
if (flags & 128) return 'dangerous'
|
||||
if (flags & 512) return 'sensitive'
|
||||
return 'document'
|
||||
}
|
||||
</script>
|
||||
@@ -133,9 +133,19 @@
|
||||
{:else if viewer === 'markdown'}
|
||||
<MarkdownRenderer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{:else if viewer === 'text'}
|
||||
<TextViewer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{#if detectLanguage(file.name)}
|
||||
<CodeViewer src={fileUrl(cxid, file.idx, false, password)} rawUrl={rawUrl(cxid, file.idx, password)} fileName={file.name} />
|
||||
{:else}
|
||||
<TextViewer src={fileUrl(cxid, file.idx, false, password)} rawUrl={rawUrl(cxid, file.idx, password)} fileName={file.name} />
|
||||
{/if}
|
||||
{:else if viewer === 'pdf'}
|
||||
<PdfViewer src={fileUrl(cxid, file.idx, false, password)} />
|
||||
{:else if viewer === 'docx'}
|
||||
<DocxViewer src={fileUrl(cxid, file.idx, false, password)} downloadUrl={fileUrl(cxid, file.idx, true, password)} {file} />
|
||||
{:else if viewer === 'executable' || viewer === 'dangerous'}
|
||||
<ExecutableWarning {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{:else if viewer === 'sensitive'}
|
||||
<SensitiveWarning {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{:else}
|
||||
<DocumentCard {file} downloadUrl={fileUrl(cxid, file.idx, true, password)} />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user