v0.2.2
new: Post auto load fix: zip file preview
This commit is contained in:
parent
f1d6faeb75
commit
1add8ce529
File diff suppressed because one or more lines are too long
1
dist/assets/index-Cq-5lgfU.css
vendored
Normal file
1
dist/assets/index-Cq-5lgfU.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
post{display:block}post[filetype=mp4] span.duration,post[filetype=webm] span.duration,post[filetype=zip] span.duration{background-color:#fff;color:#000}post span.duration{position:absolute;background-color:#00000050;bottom:.3rem;right:.3rem;padding:2px 4px;border-radius:4px;font-size:12px;text-transform:uppercase;z-index:2}post img{border-radius:10px;height:100%;width:100%}post video{border-radius:10px;height:100%;width:100%;object-fit:cover;position:absolute}#post section{background-color:#2f2f45;border-radius:20px;padding:20px}#post div.main{width:calc(100vw - 300px - 4rem);padding-right:10px;display:flex;flex-direction:column}@media (max-width: 800px){#post div.main{width:100%}}#post div.main::-webkit-scrollbar{background-color:#000;width:4px}#post div.main::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}#post div.main>h3{padding-left:1rem;margin-block:1rem}#post div.main div.viewer{height:calc(100vh - 2rem);display:flex;justify-content:center;align-items:center;background-color:#000;border-radius:20px;overflow:hidden}#post div.main div.viewer img{max-width:100%;max-height:100%}#post div.main div.viewer video{max-width:100%;max-height:100%}#post div.main section.commentary *{text-wrap:wrap;word-break:break-word}#post div.sidebar{position:fixed;top:1rem;right:1rem;display:flex;flex-direction:column;gap:.4rem;width:300px;overflow:scroll;overflow-x:hidden;height:calc(100vh - 2rem);border-radius:20px}@media (max-width: 800px){#post div.sidebar{position:relative;width:100%;overflow:visible;height:100%;padding-inline:1rem;padding-bottom:1rem}}#post div.sidebar::-webkit-scrollbar{background-color:#000;width:0px}#post div.sidebar::-webkit-scrollbar-thumb{background-color:#aeaeec}#post div.sidebar h3{padding-left:1rem;margin-block:.6rem}#post div.sidebar .post-info{background-color:#2f2f45;border-radius:20px;padding:20px;display:flex;flex-direction:column;gap:.4rem}#post div.sidebar div.property{display:flex;gap:.6rem;align-items:center}#post div.sidebar div.property div.property-values{display:flex;gap:.4rem}#post div.sidebar div.property div.property-values span.property-value{background-color:#525278;color:#aeaeec;padding:2px 4px;border-radius:4px}#post div.sidebar div.inline{display:flex;gap:1rem}#post div.sidebar div.post-tags{display:flex;flex-direction:column;gap:.2rem}#post div.sidebar div.post-tags div.tag{align-items:center}#post div.sidebar div.post-tags div.tag a.tag-name{word-break:break-word;color:#d1d1ee;text-decoration:none}#post div.sidebar div.post-tags div.tag span.tag-post-count{background-color:#525278;color:#aeaeec;padding:0 4px;border-radius:4px;font-size:12px;margin-left:.4rem}page#root .loader{text-align:center;padding-block:2rem}body{background-color:#1e1e2c;color:#d1d1ee;margin:0;font-family:Microsoft Yahei;font-size:14px}body::-webkit-scrollbar{background-color:#000;width:8px}body::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}app{display:block}app view{display:block}app view page{min-height:100%;padding:1rem;display:block}
|
1
dist/assets/index-bPuxyZ9T.css
vendored
1
dist/assets/index-bPuxyZ9T.css
vendored
@ -1 +0,0 @@
|
|||||||
post{display:block}post[filetype=mp4] span.duration,post[filetype=webm] span.duration{background-color:#fff;color:#000}post span.duration{position:absolute;background-color:#00000050;bottom:.3rem;right:.3rem;padding:2px 4px;border-radius:4px;font-size:12px;text-transform:uppercase;z-index:2}post img{border-radius:10px;height:100%;width:100%}post video{border-radius:10px;height:100%;width:100%;object-fit:cover;position:absolute}#post section{background-color:#2f2f45;border-radius:20px;padding:20px}#post div.main{width:calc(100vw - 300px - 4rem);padding-right:10px;display:flex;flex-direction:column}@media (max-width: 800px){#post div.main{width:100%}}#post div.main::-webkit-scrollbar{background-color:#000;width:4px}#post div.main::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}#post div.main>h3{padding-left:1rem;margin-block:1rem}#post div.main div.viewer{height:calc(100vh - 2rem);display:flex;justify-content:center;align-items:center;background-color:#000;border-radius:20px;overflow:hidden}#post div.main div.viewer img{max-width:100%;max-height:100%}#post div.main div.viewer video{max-width:100%;max-height:100%}#post div.main section.commentary *{text-wrap:wrap;word-break:break-word}#post div.sidebar{position:fixed;top:1rem;right:1rem;display:flex;flex-direction:column;gap:.4rem;width:300px;overflow:scroll;overflow-x:hidden;height:calc(100vh - 2rem);border-radius:20px}@media (max-width: 800px){#post div.sidebar{position:relative;width:100%;overflow:visible;height:100%;padding-inline:1rem;padding-bottom:1rem}}#post div.sidebar::-webkit-scrollbar{background-color:#000;width:0px}#post div.sidebar::-webkit-scrollbar-thumb{background-color:#aeaeec}#post div.sidebar h3{padding-left:1rem;margin-block:.6rem}#post div.sidebar .post-info{background-color:#2f2f45;border-radius:20px;padding:20px;display:flex;flex-direction:column;gap:.4rem}#post div.sidebar div.property{display:flex;gap:.6rem;align-items:center}#post div.sidebar div.property div.property-values{display:flex;gap:.4rem}#post div.sidebar div.property div.property-values span.property-value{background-color:#525278;color:#aeaeec;padding:2px 4px;border-radius:4px}#post div.sidebar div.inline{display:flex;gap:1rem}#post div.sidebar div.post-tags{display:flex;flex-direction:column;gap:.2rem}#post div.sidebar div.post-tags div.tag{align-items:center}#post div.sidebar div.post-tags div.tag a.tag-name{word-break:break-word;color:#d1d1ee;text-decoration:none}#post div.sidebar div.post-tags div.tag span.tag-post-count{background-color:#525278;color:#aeaeec;padding:0 4px;border-radius:4px;font-size:12px;margin-left:.4rem}body{background-color:#1e1e2c;color:#d1d1ee;margin:0;font-family:Microsoft Yahei;font-size:14px}body::-webkit-scrollbar{background-color:#000;width:8px}body::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}app{display:block}app view{display:block}app view page{min-height:100%;padding:1rem;display:block}
|
|
4
dist/index.html
vendored
4
dist/index.html
vendored
@ -5,8 +5,8 @@
|
|||||||
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Danbooru Viewer v0.1</title>
|
<title>Danbooru Viewer v0.1</title>
|
||||||
<script type="module" crossorigin src="/assets/index-C_aOc7tm.js"></script>
|
<script type="module" crossorigin src="/assets/index-BIoKxl_Q.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-bPuxyZ9T.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-Cq-5lgfU.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
@import '/src/component/PostGrid/$PostGrid';
|
@import '/src/component/PostGrid/$PostGrid';
|
||||||
@import '/src/component/PostTile/$PostTile';
|
@import '/src/component/PostTile/$PostTile';
|
||||||
@import '/src/route/posts/$post';
|
@import '/src/route/posts/$post';
|
||||||
|
@import '/src/route/home/$home';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #1e1e2c;
|
background-color: #1e1e2c;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "danbooru-viewer",
|
"name": "danbooru-viewer",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest"
|
"@types/bun": "latest"
|
||||||
},
|
},
|
||||||
|
@ -35,7 +35,7 @@ export class $PostTile extends $Container {
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
.on('mouseenter', () => {
|
.on('mouseenter', () => {
|
||||||
if (!this.$video?.isPlaying) this.$video?.src(this.post.file_url).hide(false).play().catch(err => undefined)
|
if (!this.$video?.isPlaying) this.$video?.src(this.post.large_file_url).hide(false).play().catch(err => undefined)
|
||||||
})
|
})
|
||||||
.on('mouseleave', () => {
|
.on('mouseleave', () => {
|
||||||
this.$video?.pause().currentTime(0).hide(true);
|
this.$video?.pause().currentTime(0).hide(true);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
post {
|
post {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
&[filetype="mp4"], &[filetype="webm"] {
|
&[filetype="mp4"], &[filetype="webm"], &[filetype="zip"] {
|
||||||
span.duration {
|
span.duration {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
@ -6,7 +6,7 @@ import { $PostTile } from "../../component/PostTile/$PostTile";
|
|||||||
|
|
||||||
export const home_route = new Route((path) => {
|
export const home_route = new Route((path) => {
|
||||||
if (path === '/posts' || path === '/') return '/';
|
if (path === '/posts' || path === '/') return '/';
|
||||||
}, ({record, loaded}) => {
|
}, ({record}) => {
|
||||||
const $page = $('page').id('root');
|
const $page = $('page').id('root');
|
||||||
async function load(tags: string) {
|
async function load(tags: string) {
|
||||||
const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags} : undefined, 100)
|
const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags} : undefined, 100)
|
||||||
@ -14,7 +14,29 @@ export const home_route = new Route((path) => {
|
|||||||
posts.filter(post => post.file_url).map(post => new $PostTile(post))
|
posts.filter(post => post.file_url).map(post => new $PostTile(post))
|
||||||
]).on('resize', () => { resizeCheck() });
|
]).on('resize', () => { resizeCheck() });
|
||||||
resizeCheck();
|
resizeCheck();
|
||||||
return $grid
|
let last_post = posts.at(-1)!;
|
||||||
|
let loaded = false;
|
||||||
|
let ended = posts.length !== 100;
|
||||||
|
const $loader = $('div').class('loader').content( ended ? `It's End` : 'Loading...');
|
||||||
|
window.addEventListener('scroll', async () => {
|
||||||
|
if (!$grid.inDOM()) return;
|
||||||
|
if (ended) return;
|
||||||
|
if (loaded) return;
|
||||||
|
if (document.documentElement.scrollTop < document.documentElement.scrollHeight - innerHeight * 3) return;
|
||||||
|
loaded = true;
|
||||||
|
const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags, id: `..${last_post.id - 1}`} : {id: `..${last_post.id - 1}`}, 100)
|
||||||
|
$grid.insert(
|
||||||
|
posts.filter(post => post.file_url).map(post => new $PostTile(post))
|
||||||
|
).render();
|
||||||
|
if (posts.length !== 100) {
|
||||||
|
$loader.content(`It's End`);
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
last_post = posts.at(-1)!;
|
||||||
|
loaded = false;
|
||||||
|
})
|
||||||
|
|
||||||
|
return {$grid, $loader}
|
||||||
|
|
||||||
function resizeCheck() {
|
function resizeCheck() {
|
||||||
if (innerWidth < 350) $grid.column(1);
|
if (innerWidth < 350) $grid.column(1);
|
||||||
@ -37,8 +59,11 @@ export const home_route = new Route((path) => {
|
|||||||
} else {
|
} else {
|
||||||
$page.clear();
|
$page.clear();
|
||||||
}
|
}
|
||||||
const $grid = await load(tags);
|
const {$grid, $loader} = await load(tags);
|
||||||
$page.content($grid);
|
$page.content([
|
||||||
|
$grid,
|
||||||
|
$loader
|
||||||
|
]);
|
||||||
$grid.render();
|
$grid.render();
|
||||||
gridManager.set(tags, $grid);
|
gridManager.set(tags, $grid);
|
||||||
Router.recoveryScrollPosition();
|
Router.recoveryScrollPosition();
|
||||||
|
6
src/route/home/_$home.scss
Normal file
6
src/route/home/_$home.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
page#root {
|
||||||
|
.loader {
|
||||||
|
text-align: center;
|
||||||
|
padding-block: 2rem;
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ export const posts_route = new Route('/posts/:id', ({params}) => {
|
|||||||
const post = Post.manager.get(+params.id) ?? await Post.fetch(booru, +params.id);
|
const post = Post.manager.get(+params.id) ?? await Post.fetch(booru, +params.id);
|
||||||
ele.$viewer.content([
|
ele.$viewer.content([
|
||||||
post.isVideo
|
post.isVideo
|
||||||
? $('video').src(post.file_url).controls(true)
|
? $('video').src(post.file_ext === 'zip' ? post.large_file_url : post.file_url).controls(true)
|
||||||
: $('img').src(post.large_file_url).once('load', (e, $img) => { $img.src(post.file_url)})
|
: $('img').src(post.large_file_url).once('load', (e, $img) => { $img.src(post.file_url)})
|
||||||
])
|
])
|
||||||
value.uploader$.set(post.uploader$);
|
value.uploader$.set(post.uploader$);
|
||||||
|
@ -46,8 +46,6 @@ export class Post {
|
|||||||
});
|
});
|
||||||
const userIds = [...new Set(dataArray.map(data => [data.approver_id, data.uploader_id].detype(null)).flat())];
|
const userIds = [...new Set(dataArray.map(data => [data.approver_id, data.uploader_id].detype(null)).flat())];
|
||||||
User.fetchMultiple(booru, {id: userIds}).then(() => list.forEach(post => post.update$()));
|
User.fetchMultiple(booru, {id: userIds}).then(() => list.forEach(post => post.update$()));
|
||||||
// const tagNames = new Set(dataArray.map(data => data.tag_string.split(' ')).flat());
|
|
||||||
// Tag.fetchMultiple(booru, {name: {_comma: [...tagNames.values()].toString()}})
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +60,7 @@ export class Post {
|
|||||||
get pathname() { return `/posts/${this.id}` }
|
get pathname() { return `/posts/${this.id}` }
|
||||||
get uploader() { return User.manager.get(this.uploader_id); }
|
get uploader() { return User.manager.get(this.uploader_id); }
|
||||||
get approver() { if (this.approver_id) return User.manager.get(this.approver_id); else return null }
|
get approver() { if (this.approver_id) return User.manager.get(this.approver_id); else return null }
|
||||||
get isVideo() { return this.file_ext === 'mp4' || this.file_ext === 'webm' }
|
get isVideo() { return this.file_ext === 'mp4' || this.file_ext === 'webm' || this.file_ext === 'zip' }
|
||||||
get tags() {
|
get tags() {
|
||||||
const tag_list = this.tag_string.split(' ');
|
const tag_list = this.tag_string.split(' ');
|
||||||
return [...Tag.manager.values()].filter(tag => tag_list.includes(tag.name))
|
return [...Tag.manager.values()].filter(tag => tag_list.includes(tag.name))
|
||||||
|
@ -66,9 +66,9 @@ export interface TagSearchParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum TagCategory {
|
export enum TagCategory {
|
||||||
General,
|
General = 0,
|
||||||
Artist,
|
Artist = 1,
|
||||||
Copyright,
|
Copyright = 3,
|
||||||
Character,
|
Character = 4,
|
||||||
Meta
|
Meta = 5
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user