v0.3.3
update: $Router package. new: open in original site button. change: searchbar input background remove transparency. change: post page video player disable picture in picture. new: post page sidebar detail add copy file link button and copy webm link button. new: ugoria format will show icon on $PostTile. new: $IconButton new: Post.isUgoria
This commit is contained in:
parent
6104d9003f
commit
86c2d5aa9f
1
dist/assets/index-B240dcNf.css
vendored
Normal file
1
dist/assets/index-B240dcNf.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
dist/assets/index-qRel_iFf.css
vendored
1
dist/assets/index-qRel_iFf.css
vendored
File diff suppressed because one or more lines are too long
4
dist/index.html
vendored
4
dist/index.html
vendored
@ -7,8 +7,8 @@
|
|||||||
<title>Danbooru Viewer v0.2.5</title>
|
<title>Danbooru Viewer v0.2.5</title>
|
||||||
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
|
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
|
||||||
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
|
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
|
||||||
<script type="module" crossorigin src="/assets/index-BfZu1R1a.js"></script>
|
<script type="module" crossorigin src="/assets/index-C21fHnwq.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-qRel_iFf.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-B240dcNf.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/component/Searchbar/$Searchbar';
|
@import '/src/component/Searchbar/$Searchbar';
|
||||||
|
@import '/src/component/IconButton/$IconButton';
|
||||||
@import '/src/route/post/$post';
|
@import '/src/route/post/$post';
|
||||||
@import '/src/route/gallery/$gallery';
|
@import '/src/route/gallery/$gallery';
|
||||||
|
|
||||||
@ -139,9 +140,10 @@ router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background-color: #aeaeec;
|
background-color: var(--secondary-color-dark);
|
||||||
padding: 2px 4px;
|
color: var(--secondary-color);
|
||||||
border-radius: 0.4rem;
|
padding: 0.8rem 1.2rem;
|
||||||
|
border-radius: 1rem;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "danbooru-viewer",
|
"name": "danbooru-viewer",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"vite": "^5.4.8"
|
"vite": "^5.4.8"
|
||||||
|
28
src/component/IconButton/$IconButton.ts
Normal file
28
src/component/IconButton/$IconButton.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { $Button, type $ContainerContentBuilder } from "elexis";
|
||||||
|
|
||||||
|
export class $IconButton extends $Button {
|
||||||
|
$icon = $('ion-icon');
|
||||||
|
$label = $('span');
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.addStaticClass('icon')
|
||||||
|
this.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private build() {
|
||||||
|
super.content([
|
||||||
|
this.$icon,
|
||||||
|
this.$label
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
content(children: $ContainerContentBuilder<typeof this.$label>): this {
|
||||||
|
this.$label.content(children);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
icon(name: string) {
|
||||||
|
this.$icon.name(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
19
src/component/IconButton/_$IconButton.scss
Normal file
19
src/component/IconButton/_$IconButton.scss
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
button.icon {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.4rem;
|
||||||
|
background-color: transparent;
|
||||||
|
ion-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--background-color-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.vertical {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ export class $PostTile extends $Container {
|
|||||||
this.post.isVideo
|
this.post.isVideo
|
||||||
? $('div').class('video-detail').content([
|
? $('div').class('video-detail').content([
|
||||||
this.post.hasSound ? $('ion-icon').name('volume-medium-outline') : null,
|
this.post.hasSound ? $('ion-icon').name('volume-medium-outline') : null,
|
||||||
|
this.post.isUgoria ? $('ion-icon').name('images-outline') : null,
|
||||||
$('span').class('duration').content(this.duration$)
|
$('span').class('duration').content(this.duration$)
|
||||||
]) : null,
|
]) : null,
|
||||||
// Gif
|
// Gif
|
||||||
|
@ -29,7 +29,8 @@ post-tile {
|
|||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
bottom: 0.3rem;
|
bottom: 0.3rem;
|
||||||
right: 0.3rem;
|
right: 0.3rem;
|
||||||
padding: 2px 4px;
|
padding: 0.2em 0.4em;
|
||||||
|
height: 1rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -39,7 +40,12 @@ post-tile {
|
|||||||
// text-shadow: 0 0 0.5em var(--background-color);
|
// text-shadow: 0 0 0.5em var(--background-color);
|
||||||
|
|
||||||
ion-icon {
|
ion-icon {
|
||||||
font-size: 1.5em;
|
font-size: 1.4rem;
|
||||||
|
|
||||||
|
&[name="images-outline"] {
|
||||||
|
padding: 0.1rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span.duration {
|
span.duration {
|
||||||
|
@ -10,7 +10,7 @@ searchbar {
|
|||||||
|
|
||||||
div.input-container {
|
div.input-container {
|
||||||
margin-top: 0.4rem;
|
margin-top: 0.4rem;
|
||||||
background-color: color-mix(in srgb, var(--background-color-light) 70%, transparent);
|
background-color: color-mix(in srgb, var(--background-color-light) 100%, transparent);
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
|
12
src/main.ts
12
src/main.ts
@ -7,15 +7,18 @@ import { $PostGrid } from './component/PostGrid/$PostGrid';
|
|||||||
import { $Router, $RouterNavigationDirection } from '@elexis/router';
|
import { $Router, $RouterNavigationDirection } from '@elexis/router';
|
||||||
import { $Searchbar } from './component/Searchbar/$Searchbar';
|
import { $Searchbar } from './component/Searchbar/$Searchbar';
|
||||||
import { $IonIcon } from './component/IonIcon/$IonIcon';
|
import { $IonIcon } from './component/IonIcon/$IonIcon';
|
||||||
|
import { $IconButton } from './component/IconButton/$IconButton';
|
||||||
// declare elexis module
|
// declare elexis module
|
||||||
declare module 'elexis' {
|
declare module 'elexis' {
|
||||||
export namespace $ {
|
export namespace $ {
|
||||||
export interface TagNameElementMap {
|
export interface TagNameElementMap {
|
||||||
'ion-icon': typeof $IonIcon
|
'ion-icon': typeof $IonIcon;
|
||||||
|
'icon-button': typeof $IconButton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$.registerTagName('ion-icon', $IonIcon)
|
$.registerTagName('ion-icon', $IonIcon)
|
||||||
|
$.registerTagName('icon-button', $IconButton)
|
||||||
$.anchorHandler = ($a) => { $.open($a.href(), $a.target())}
|
$.anchorHandler = ($a) => { $.open($a.href(), $a.target())}
|
||||||
// settings
|
// settings
|
||||||
export const [danbooru, safebooru]: Booru[] = [
|
export const [danbooru, safebooru]: Booru[] = [
|
||||||
@ -48,12 +51,15 @@ $(document.body).content([
|
|||||||
$('ion-icon').class('search').name('search-outline').title('Search')
|
$('ion-icon').class('search').name('search-outline').title('Search')
|
||||||
.self($self => $Router.events.on('stateChange', ({beforeURL, afterURL}) => {if (beforeURL.hash === '#search') $self.hide(false); if (afterURL.hash === '#search') $self.hide(true)}))
|
.self($self => $Router.events.on('stateChange', ({beforeURL, afterURL}) => {if (beforeURL.hash === '#search') $self.hide(false); if (afterURL.hash === '#search') $self.hide(true)}))
|
||||||
.on('click', () => $.open(location.href + '#search')),
|
.on('click', () => $.open(location.href + '#search')),
|
||||||
// Switch Button
|
// Switch Booru
|
||||||
$('ion-icon').class('switch').name('swap-horizontal').title('Switch Booru')
|
$('ion-icon').class('switch').name('swap-horizontal').title('Switch Booru')
|
||||||
.on('click', () => {
|
.on('click', () => {
|
||||||
if (Booru.used === danbooru) Booru.set(safebooru);
|
if (Booru.used === danbooru) Booru.set(safebooru);
|
||||||
else Booru.set(danbooru);
|
else Booru.set(danbooru);
|
||||||
})
|
}),
|
||||||
|
// Open Booru
|
||||||
|
$('ion-icon').class('open').name('open-outline').title('Open in Original Site')
|
||||||
|
.on('click', () => $.open(location.href.replace(location.origin, Booru.used.origin))),
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
// Searchbar
|
// Searchbar
|
||||||
|
@ -11,7 +11,7 @@ export const post_route = $('route').path('/posts/:id').id('post').builder(({$ro
|
|||||||
$('div').class('viewer').content(async () => {
|
$('div').class('viewer').content(async () => {
|
||||||
await post.ready;
|
await post.ready;
|
||||||
return post.isVideo
|
return post.isVideo
|
||||||
? $('video').height(post.image_height).width(post.image_width).src(post.file_ext === 'zip' ? post.large_file_url : post.file_url).controls(true).autoplay(true).loop(true)
|
? $('video').height(post.image_height).width(post.image_width).src(post.file_ext === 'zip' ? post.large_file_url : post.file_url).controls(true).autoplay(true).loop(true).disablePictureInPicture(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)})
|
||||||
}),
|
}),
|
||||||
$('div').class('content').content([
|
$('div').class('content').content([
|
||||||
@ -46,14 +46,36 @@ export const post_route = $('route').path('/posts/:id').id('post').builder(({$ro
|
|||||||
new $Property('favorites').name('Favorites').value(post.favorites$),
|
new $Property('favorites').name('Favorites').value(post.favorites$),
|
||||||
new $Property('score').name('Score').value(post.score$)
|
new $Property('score').name('Score').value(post.score$)
|
||||||
]),
|
]),
|
||||||
$('button').content('Copy link').on('click', (e, $button) => {
|
$('div').class('buttons').content([
|
||||||
e.preventDefault();
|
$('icon-button').class('vertical').icon('link-outline').content(Booru.name$)
|
||||||
navigator.clipboard.writeText(`${Booru.used.origin}${location.pathname}`);
|
.on('click', (e, $button) => {
|
||||||
$button.content('Copied!');
|
e.preventDefault();
|
||||||
setTimeout(() => {
|
navigator.clipboard.writeText(`${Booru.used.origin}${location.pathname}`);
|
||||||
$button.content('Copy link')
|
$button.content('Copied!');
|
||||||
}, 2000);
|
setTimeout(() => {
|
||||||
})
|
$button.content(Booru.name$)
|
||||||
|
}, 2000);
|
||||||
|
}),
|
||||||
|
$('icon-button').class('vertical').icon('link-outline').content(`File`)
|
||||||
|
.on('click', (e, $button) => {
|
||||||
|
e.preventDefault();
|
||||||
|
navigator.clipboard.writeText(post.file_url);
|
||||||
|
$button.content('Copied!');
|
||||||
|
setTimeout(() => {
|
||||||
|
$button.content('File')
|
||||||
|
}, 2000);
|
||||||
|
}),
|
||||||
|
$('icon-button').class('vertical').icon('link-outline').content(`Webm`)
|
||||||
|
.on('click', (e, $button) => {
|
||||||
|
e.preventDefault();
|
||||||
|
navigator.clipboard.writeText(post.previewURL);
|
||||||
|
$button.content('Copied!');
|
||||||
|
setTimeout(() => {
|
||||||
|
$button.content('Webm')
|
||||||
|
}, 2000);
|
||||||
|
})
|
||||||
|
.hide(true).self(async ($button) => { await post.ready; if (post.file_ext === 'zip') $button.hide(false) })
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
$('div').class('post-tags').content(async $tags => {
|
$('div').class('post-tags').content(async $tags => {
|
||||||
const tags = await post.fetchTags();
|
const tags = await post.fetchTags();
|
||||||
|
@ -116,6 +116,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.property {
|
div.property {
|
||||||
|
@ -96,6 +96,7 @@ export class Post extends $EventManager<{update: []}> {
|
|||||||
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' || this.file_ext === 'zip' }
|
get isVideo() { return this.file_ext === 'mp4' || this.file_ext === 'webm' || this.file_ext === 'zip' }
|
||||||
get isGif() { return this.file_ext === 'gif' }
|
get isGif() { return this.file_ext === 'gif' }
|
||||||
|
get isUgoria() { return this.file_ext === 'zip' }
|
||||||
get hasSound() { return this.tag_string_meta.includes('sound') }
|
get hasSound() { return this.tag_string_meta.includes('sound') }
|
||||||
get tags() {
|
get tags() {
|
||||||
const tag_list = this.tag_string.split(' ');
|
const tag_list = this.tag_string.split(' ');
|
||||||
|
Loading…
Reference in New Issue
Block a user