v0.9.0
- change: document element scroll behavior smooth. - new: hotkey supported: - browser navigation back and forward. - post grid navigation. - post favorites.
This commit is contained in:
parent
84f52ed030
commit
d6be4c0c62
1
dist/assets/index-BMZsSbMp.js
vendored
Normal file
1
dist/assets/index-BMZsSbMp.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-ByWqsQtl.css
vendored
Normal file
1
dist/assets/index-ByWqsQtl.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-D689878Y.css
vendored
1
dist/assets/index-D689878Y.css
vendored
File diff suppressed because one or more lines are too long
1
dist/assets/index-D8tVsP8g.js
vendored
1
dist/assets/index-D8tVsP8g.js
vendored
File diff suppressed because one or more lines are too long
4
dist/index.html
vendored
4
dist/index.html
vendored
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
gtag('config', 'G-59HBGP98WR');
|
gtag('config', 'G-59HBGP98WR');
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-D8tVsP8g.js"></script>
|
<script type="module" crossorigin src="/assets/index-BMZsSbMp.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D689878Y.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-ByWqsQtl.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
html {
|
html {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
scroll-behavior: smooth;
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
background-color: var(--secondary-color-1);
|
background-color: var(--secondary-color-1);
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "danbooru-viewer",
|
"name": "danbooru-viewer",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.2",
|
"version": "0.9.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun x vite",
|
"dev": "bun x vite",
|
||||||
"build": "bun x vite build",
|
"build": "bun x vite build",
|
||||||
|
@ -45,10 +45,11 @@ export class $Drawer extends $Container {
|
|||||||
$('icon-button').icon('log-in-outline').content('Logout').on('dblclick', () => Booru.used.logout()).hide(true)
|
$('icon-button').icon('log-in-outline').content('Logout').on('dblclick', () => Booru.used.logout()).hide(true)
|
||||||
.self(($div => Booru.events.on('login', () => $div.hide(false)).on('logout', () => $div.hide(true)))),
|
.self(($div => Booru.events.on('login', () => $div.hide(false)).on('logout', () => $div.hide(true)))),
|
||||||
|
|
||||||
$('icon-button').icon('swap-horizontal').content('Logout').class('switch').content('Switch Booru')
|
$('icon-button').icon('swap-horizontal').class('switch').content('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);
|
||||||
|
this.close();
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
@ -2,6 +2,7 @@ import { $Layout, type $LayoutEventMap } from "@elexis/layout";
|
|||||||
import { Booru } from "../../structure/Booru";
|
import { Booru } from "../../structure/Booru";
|
||||||
import { Post } from "../../structure/Post";
|
import { Post } from "../../structure/Post";
|
||||||
import { $PostTile } from "../PostTile/$PostTile";
|
import { $PostTile } from "../PostTile/$PostTile";
|
||||||
|
import { $Input } from "elexis/lib/node/$Input";
|
||||||
|
|
||||||
interface $PostGridOptions {
|
interface $PostGridOptions {
|
||||||
tags?: string
|
tags?: string
|
||||||
@ -13,6 +14,7 @@ export class $PostGrid extends $Layout<$PostGridEventMap> {
|
|||||||
tags?: string;
|
tags?: string;
|
||||||
finished = false;
|
finished = false;
|
||||||
limit = 100;
|
limit = 100;
|
||||||
|
$focus = $.focus();
|
||||||
constructor(options?: $PostGridOptions) {
|
constructor(options?: $PostGridOptions) {
|
||||||
super();
|
super();
|
||||||
this.tags = options?.tags;
|
this.tags = options?.tags;
|
||||||
@ -34,6 +36,29 @@ export class $PostGrid extends $Layout<$PostGridEventMap> {
|
|||||||
this.on('resize', () => this.resize())
|
this.on('resize', () => this.resize())
|
||||||
this.events.fire('startLoad');
|
this.events.fire('startLoad');
|
||||||
this.loader();
|
this.loader();
|
||||||
|
this.$focus.layer(100).loop(false).scrollThreshold($.rem(2) + 60);
|
||||||
|
|
||||||
|
$.keys($(window))
|
||||||
|
.if(e => {
|
||||||
|
if ($(e.target) instanceof $Input) return;
|
||||||
|
if (!this.inDOM()) return;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.keydown('Tab', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.shiftKey) this.$focus.prev();
|
||||||
|
else this.$focus.next();
|
||||||
|
})
|
||||||
|
.keydown(['w', 'W'], e => { e.preventDefault(); this.$focus.up(); })
|
||||||
|
.keydown(['s', 'S'], e => { e.preventDefault(); this.$focus.down(); })
|
||||||
|
.keydown(['d', 'D'], e => { e.preventDefault(); this.$focus.right(); })
|
||||||
|
.keydown(['a', 'A'], e => { e.preventDefault(); this.$focus.left(); })
|
||||||
|
.keydown([' ', 'Enter'], e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const focused = this.$focus.currentLayer?.currentFocus;
|
||||||
|
if (focused instanceof $PostTile) $.open(`/posts/${focused.post.id}`);
|
||||||
|
})
|
||||||
|
.keydown(['Escape'], e => { e.preventDefault(); this.$focus.blur(); })
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async loader() {
|
protected async loader() {
|
||||||
@ -63,7 +88,8 @@ export class $PostGrid extends $Layout<$PostGridEventMap> {
|
|||||||
this.$posts.set(post, $post);
|
this.$posts.set(post, $post);
|
||||||
this.posts.add(post);
|
this.posts.add(post);
|
||||||
}
|
}
|
||||||
const $posts = [...this.orderMap.values()].map(post => this.$posts.get(post));
|
this.$focus.layer(100).removeAll();
|
||||||
|
const $posts = [...this.orderMap.values()].map(post => this.$posts.get(post)?.self(this.$focus.layer(100).add));
|
||||||
this.content($posts).render();
|
this.content($posts).render();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
layout.post-grid {
|
layout.post-grid {
|
||||||
margin-top: 0.4rem;
|
margin-top: 0.4rem;
|
||||||
|
|
||||||
|
&:has(post-tile[focus]) {
|
||||||
|
post-tile:not([focus]) {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
post-tile:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,7 +7,12 @@ post-tile {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
outline: transparent solid 2px;
|
||||||
|
|
||||||
|
&[focus] {
|
||||||
|
outline: var(--secondary-color-9) solid 2px;
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.02);
|
transform: scale(1.02);
|
||||||
|
13
src/main.ts
13
src/main.ts
@ -1,7 +1,7 @@
|
|||||||
import 'elexis';
|
import 'elexis';
|
||||||
import '@elexis/layout';
|
import '@elexis/layout';
|
||||||
import '@elexis/router';
|
import '@elexis/router';
|
||||||
import { Booru, type BooruOptions } from './structure/Booru';
|
import { Booru } from './structure/Booru';
|
||||||
import { post_route } from './route/post/$post_route';
|
import { post_route } from './route/post/$post_route';
|
||||||
import { $PostGrid } from './component/PostGrid/$PostGrid';
|
import { $PostGrid } from './component/PostGrid/$PostGrid';
|
||||||
import { $Router, $RouterNavigationDirection } from '@elexis/router';
|
import { $Router, $RouterNavigationDirection } from '@elexis/router';
|
||||||
@ -10,6 +10,7 @@ import { $IonIcon } from './component/IonIcon/$IonIcon';
|
|||||||
import { $IconButton } from './component/IconButton/$IconButton';
|
import { $IconButton } from './component/IconButton/$IconButton';
|
||||||
import { $login_route } from './route/login/$login_route';
|
import { $login_route } from './route/login/$login_route';
|
||||||
import { $Drawer } from './component/Drawer/$Drawer';
|
import { $Drawer } from './component/Drawer/$Drawer';
|
||||||
|
import { $Input } from 'elexis/lib/node/$Input';
|
||||||
// declare elexis module
|
// declare elexis module
|
||||||
declare module 'elexis' {
|
declare module 'elexis' {
|
||||||
export namespace $ {
|
export namespace $ {
|
||||||
@ -117,6 +118,7 @@ $(document.body).content([
|
|||||||
const TX = 2;
|
const TX = 2;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
function intro() {
|
function intro() {
|
||||||
|
$(document.documentElement).css({scrollBehavior: 'auto'});
|
||||||
const transform = $.call(() => {
|
const transform = $.call(() => {
|
||||||
switch ($Router.navigationDirection) {
|
switch ($Router.navigationDirection) {
|
||||||
case $RouterNavigationDirection.Forward: return [`translateX(${TX}%)`, `translateX(0%)`];
|
case $RouterNavigationDirection.Forward: return [`translateX(${TX}%)`, `translateX(0%)`];
|
||||||
@ -134,10 +136,12 @@ $(document.body).content([
|
|||||||
easing: 'ease'
|
easing: 'ease'
|
||||||
}, () => {
|
}, () => {
|
||||||
e.switched();
|
e.switched();
|
||||||
|
$(document.documentElement).css({scrollBehavior: ''});
|
||||||
e.nextContent.element?.removeClass('animated')
|
e.nextContent.element?.removeClass('animated')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function outro() {
|
function outro() {
|
||||||
|
$(document.documentElement).css({scrollBehavior: 'auto'});
|
||||||
const transform = $.call(() => {
|
const transform = $.call(() => {
|
||||||
switch ($Router.navigationDirection) {
|
switch ($Router.navigationDirection) {
|
||||||
case $RouterNavigationDirection.Forward: return [`translateX(0%)`, `translateX(-${TX}%)`];
|
case $RouterNavigationDirection.Forward: return [`translateX(0%)`, `translateX(-${TX}%)`];
|
||||||
@ -169,3 +173,10 @@ componentState(undefined, new URL(location.href))
|
|||||||
function componentState(beforeURL: URL | undefined, afterURL: URL) {
|
function componentState(beforeURL: URL | undefined, afterURL: URL) {
|
||||||
$searchbar.checkURL(beforeURL, afterURL); $drawer.checkURL(beforeURL, afterURL)
|
$searchbar.checkURL(beforeURL, afterURL); $drawer.checkURL(beforeURL, afterURL)
|
||||||
}
|
}
|
||||||
|
$.keys($(window))
|
||||||
|
.if(e => {
|
||||||
|
if ($(e.target) instanceof $Input) return;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.keydown(['q', 'Q'], e => { e.preventDefault(); if ($Router.index !== 0) $.back(); })
|
||||||
|
.keydown(['e', 'E'], e => { e.preventDefault(); if ($Router.forwardIndex !== 0) $.forward(); })
|
@ -7,6 +7,7 @@ import type { $IonIcon } from "../../component/IonIcon/$IonIcon";
|
|||||||
import { numberFormat } from "../../structure/Util";
|
import { numberFormat } from "../../structure/Util";
|
||||||
import { ClientUser } from "../../structure/ClientUser";
|
import { ClientUser } from "../../structure/ClientUser";
|
||||||
import { $VideoController } from "../../component/VideoController/$VideoController";
|
import { $VideoController } from "../../component/VideoController/$VideoController";
|
||||||
|
import { $Input } from "elexis/lib/node/$Input";
|
||||||
|
|
||||||
export const post_route = $('route').path('/posts/:id').id('post').builder(({$route, params}) => {
|
export const post_route = $('route').path('/posts/:id').id('post').builder(({$route, params}) => {
|
||||||
if (!Number(params.id)) return $('h1').content('404: POST NOT FOUND');
|
if (!Number(params.id)) return $('h1').content('404: POST NOT FOUND');
|
||||||
@ -18,6 +19,16 @@ export const post_route = $('route').path('/posts/:id').id('post').builder(({$ro
|
|||||||
original_size: [],
|
original_size: [],
|
||||||
video_play_pause: []
|
video_play_pause: []
|
||||||
}>();
|
}>();
|
||||||
|
$.keys($(window))
|
||||||
|
.if(e => {
|
||||||
|
if ($(e.target) instanceof $Input) return;
|
||||||
|
if (!$route.inDOM()) return;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.keydown(['f', 'F'], e => {
|
||||||
|
if (Booru.used.user?.favorites.has(post.id)) post.deleteFavorite();
|
||||||
|
else post.createFavorite();
|
||||||
|
})
|
||||||
return [
|
return [
|
||||||
$('div').class('viewer').content(async ($viewer) => {
|
$('div').class('viewer').content(async ($viewer) => {
|
||||||
const $video = $('video');
|
const $video = $('video');
|
||||||
|
Loading…
Reference in New Issue
Block a user