new: posts page header.
enhance: hint will show up when no posts is loaded.
fix: [css] login page `login-container` width abnormal on small width screen.
change: set route path `/posts` render same as path `/`
This commit is contained in:
defaultkavy 2024-10-08 00:24:41 +08:00
parent a992af35c2
commit 77d4f78cc2
Signed by: defaultkavy
GPG Key ID: DFBB22C4E69D7826
14 changed files with 136 additions and 87 deletions

1
dist/assets/index-BW2KEYV0.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-Djy_8N6Q.js 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

4
dist/index.html vendored
View File

@ -7,8 +7,8 @@
<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 nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
<script type="module" crossorigin src="/assets/index-La3x4wRW.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BkbpsU_v.css">
<script type="module" crossorigin src="/assets/index-Djy_8N6Q.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BW2KEYV0.css">
</head>
<body>
</body>

View File

@ -9,17 +9,19 @@
@import '/src/route/login/$login_route';
:root {
--background-color: #1e1e2c;
--background-color-lighter: #3b3b66;
--background-color-light: #24243b;
--background-color-dark: #12121f;
--background-color-darker: #07070c;
--primary-color: #d1d1ee;
--primary-color-dark: #9696b3;
--primary-color-darker: #72728d;
--secondary-color: #aeaeec;
--secondary-color-dark: #6d6da1;
--secondary-color-darker: #424268;
--secondary-color-9: #aeaeec;
--secondary-color-8: #9a9ad6;
--secondary-color-7: #7c7cb8;
--secondary-color-6: #646497;
--secondary-color-5: #545486;
--secondary-color-4: #424268;
--secondary-color-3: #3b3b66;
--secondary-color-2: #24243b;
--secondary-color-1: #1e1e2c; // background color
--secondary-color-0: #07070c;
--shadow-color: #09090e50;
--border-radius-small: 0.4rem;
@ -32,7 +34,7 @@ html {
font-size: 14px;
::-webkit-scrollbar {
background-color: var(--background-color);
background-color: var(--secondary-color-1);
width: 8px;
}
@ -43,7 +45,7 @@ html {
}
body {
overflow-x: hidden;
background-color: var(--background-color);
background-color: var(--secondary-color-1);
color: var(--primary-color);
margin: 0;
font-family: Microsoft Yahei;
@ -56,7 +58,7 @@ nav {
position: fixed;
top: 0;
z-index: 100;
background-color: color-mix(in srgb, var(--background-color) 70%, transparent);
background-color: color-mix(in srgb, var(--secondary-color-1) 70%, transparent);
justify-content: space-between;
align-items: center;
padding-inline: 1rem;
@ -69,7 +71,7 @@ nav {
gap: 0.4rem;
text-decoration: none;
.booru-name {
color: var(--secondary-color);
color: var(--secondary-color-9);
margin: 0;
}
@ -77,13 +79,13 @@ nav {
display: flex;
align-items: center;
border-radius: var(--border-radius-small);
// border: 1px solid var(--secondary-color);
// border: 1px solid var(--secondary-color-9);
// padding: 0.2rem 0.4rem;
margin: 0;
gap: 0.4rem;
.version {
color: var(--background-color);
background-color: var(--secondary-color);
color: var(--secondary-color-1);
background-color: var(--secondary-color-9);
padding: 0.2em 0.4em;
border-radius: var(--border-radius-small);
font-size: 0.8rem;
@ -92,14 +94,14 @@ nav {
.app-name {
display: none;
font-size: 1rem;
color: var(--secondary-color);
color: var(--secondary-color-9);
}
}
}
div.searchbar {
padding: 0.4rem 10%;
max-width: 500px;
background-color: color-mix(in srgb, var(--background-color-light) 30%, transparent);
background-color: color-mix(in srgb, var(--secondary-color-2) 30%, transparent);
border: 1px solid var(--primary-color-darker);
border-radius: var(--border-radius-small);
color: var(--primary-color-dark);
@ -114,12 +116,12 @@ nav {
align-items: center;
gap: 1rem;
ion-icon {
// background-color: var(--background-color);
// background-color: var(--secondary-color-1);
transition: all 0.3s ease;
border-radius: 1rem;
padding: 0.4rem;
&:hover {
background-color: color-mix(in srgb, var(--background-color-lighter) 50%, transparent);
background-color: color-mix(in srgb, var(--secondary-color-3) 50%, transparent);
}
}
ion-icon.search {
@ -134,8 +136,8 @@ nav {
align-items: center;
border-radius: 2rem;
font-weight: bolder;
color: var(--secondary-color);
background-color: var(--secondary-color-darker);
color: var(--secondary-color-9);
background-color: var(--secondary-color-4);
user-select: none;
cursor: pointer;
}
@ -163,16 +165,26 @@ router {
}
}
route#posts {
header {
margin-bottom: 1rem;
h2 {
margin: 0;
}
}
}
button {
background-color: var(--secondary-color-darker);
color: var(--secondary-color);
background-color: var(--secondary-color-4);
color: var(--secondary-color-9);
padding: 0.8rem 1.2rem;
border-radius: 1rem;
border: none;
cursor: pointer;
&:hover {
background-color: var(--secondary-color-dark);
background-color: var(--secondary-color-6);
color: var(--primary-color);
}
}
@ -183,24 +195,24 @@ ion-icon {
cursor: pointer;
&:hover {
color: var(--secondary-color);
color: var(--secondary-color-9);
}
}
a {
color: var(--secondary-color);
text-decoration: none;
color: var(--secondary-color-9);
}
input {
background-color: var(--background-color-light);
background-color: var(--secondary-color-2);
border-radius: var(--border-radius-small);
border: 1px solid var(--background-color-lighter);
border: 1px solid var(--secondary-color-3);
font-size: 0.9rem;
padding: 0.8rem 1.2rem;
color: var(--primary-color);
outline: none;
&:focus {
border-color: var(--secondary-color);
border-color: var(--secondary-color-9);
}
}

View File

@ -2,7 +2,7 @@
"name": "danbooru-viewer",
"module": "index.ts",
"type": "module",
"version": "0.3.5",
"version": "0.4.0",
"devDependencies": {
"@types/bun": "latest",
"vite": "^5.4.8"

View File

@ -15,18 +15,18 @@ drawer {
width: 300px;
max-width: 70%;
height: 100%;
background-color: var(--background-color);
background-color: var(--secondary-color-1);
border-radius: var(--border-radius-large);
z-index: 1;
overflow: hidden;
div.user-info {
background-color: var(--background-color-light);
background-color: var(--secondary-color-2);
padding: 2rem;
.username {
margin: 0;
color: var(--secondary-color);
color: var(--secondary-color-9);
cursor: pointer;
}
@ -68,8 +68,8 @@ drawer {
height: 100%;
width: 100%;
background: linear-gradient(90deg,
color-mix(in srgb, var(--background-color-dark) 50%, transparent) 0%,
color-mix(in srgb, var(--background-color-darker) 70%, transparent) 100%
color-mix(in srgb, var(--secondary-color-1) 50%, transparent) 0%,
color-mix(in srgb, var(--secondary-color-0) 70%, transparent) 100%
);
}
}

View File

@ -1,4 +1,4 @@
import { $Layout } from "@elexis/layout";
import { $Layout, type $LayoutEventMap } from "@elexis/layout";
import { Booru } from "../../structure/Booru";
import { Post } from "../../structure/Post";
import { $PostTile } from "../PostTile/$PostTile";
@ -6,7 +6,7 @@ import { $PostTile } from "../PostTile/$PostTile";
interface $PostGridOptions {
tags?: string
}
export class $PostGrid extends $Layout {
export class $PostGrid extends $Layout<$PostGridEventMap> {
posts = new Set<Post>();
$posts = new Set<$PostTile>();
tags?: string;
@ -25,10 +25,12 @@ export class $PostGrid extends $Layout {
this.removeAll();
if (this.finished) {
this.finished = false;
this.events.fire('startLoad');
this.loader();
}
})
this.on('resize', () => this.resize())
this.events.fire('startLoad');
this.loader();
}
@ -36,11 +38,19 @@ export class $PostGrid extends $Layout {
if (!this.inDOM()) return setTimeout(() => this.loader(), 100);;
while (this.inDOM() && document.documentElement.scrollHeight <= innerHeight * 2) {
const posts = await this.getPosts();
if (!posts.length) return this.finished = true;
if (!posts.length) {
this.finished = true;
if (!this.posts.size) this.events.fire('noPost');
return
}
}
if (document.documentElement.scrollTop + innerHeight > document.documentElement.scrollHeight - innerHeight * 2) {
const posts = await this.getPosts();
if (!posts.length) return this.finished = true;
if (!posts.length) {
this.finished = true;
this.events.fire('endPost');
return
}
}
setTimeout(() => this.loader(), 100);
}
@ -88,3 +98,9 @@ export class $PostGrid extends $Layout {
get sortedPosts() { return this.posts.array.sort((a, b) => +b.createdDate - +a.createdDate); }
}
interface $PostGridEventMap extends $LayoutEventMap {
startLoad: [];
noPost: [];
endPost: [];
}

View File

@ -12,7 +12,7 @@ post-tile {
&:hover {
transform: scale(1.02);
z-index: 1;
box-shadow: 0 0 10px color-mix(in srgb, var(--background-color) 50%, transparent)
box-shadow: 0 0 10px color-mix(in srgb, var(--secondary-color-1) 50%, transparent)
}
}
@ -25,7 +25,7 @@ post-tile {
}
div.video-detail, div.gif-detail {
position: absolute;
background-color: var(--background-color-lighter);//color-mix(in srgb, var(--background-color-lighter) 80%, transparent);
background-color: var(--secondary-color-3);//color-mix(in srgb, var(--secondary-color-3) 80%, transparent);
color: var(--primary-color);
bottom: 0.3rem;
right: 0.3rem;
@ -37,7 +37,7 @@ post-tile {
align-items: center;
gap: 0.2rem;
z-index: 2;
// text-shadow: 0 0 0.5em var(--background-color);
// text-shadow: 0 0 0.5em var(--secondary-color-1);
ion-icon {
font-size: 1.4rem;
@ -53,17 +53,23 @@ post-tile {
z-index: 2;
}
}
img {
height: 100%;
width: 100%;
vertical-align: top;
background-color: var(--background-color);
}
video {
height: 100%;
width: 100%;
object-fit: cover;
position: absolute;
z-index: 1;
a {
background-color: transparent;
padding: 0;
border-radius: 0;
img {
height: 100%;
width: 100%;
vertical-align: top;
background-color: var(--secondary-color-1);
}
video {
height: 100%;
width: 100%;
object-fit: cover;
position: absolute;
z-index: 1;
}
}
}

View File

@ -10,7 +10,7 @@ searchbar {
div.input-container {
margin-top: 0.4rem;
background-color: color-mix(in srgb, var(--background-color-light) 100%, transparent);
background-color: color-mix(in srgb, var(--secondary-color-2) 100%, transparent);
border-radius: var(--border-radius-small);
font-size: 1rem;
width: 500px;
@ -20,7 +20,7 @@ searchbar {
z-index: 201;
display: flex;
align-items: center;
border: 1px solid var(--secondary-color-darker);
border: 1px solid var(--secondary-color-4);
&:focus-within {
outline: none;
@ -39,8 +39,8 @@ searchbar {
tag {
display: inline-block;
padding: 0.2rem 0.4rem;
background-color: var(--secondary-color-darker);
color: var(--secondary-color);
background-color: var(--secondary-color-4);
color: var(--secondary-color-9);
border-radius: var(--border-radius-small);
cursor: pointer;
}
@ -48,10 +48,10 @@ searchbar {
ion-icon {
font-size: 20px;
color: var(--secondary-color-darker);
color: var(--secondary-color-4);
cursor: pointer;
&:hover {
color: var(--secondary-color);
color: var(--secondary-color-9);
}
}
}
@ -59,7 +59,7 @@ searchbar {
div.selection-list-container {
overflow: hidden;
border-radius: var(--border-radius-small);
background-color: var(--background-color);
background-color: var(--secondary-color-1);
z-index: 201;
max-width: calc(100% - 2rem);
width: 500px;
@ -84,10 +84,10 @@ searchbar {
gap: 1rem;
&:hover {
background-color: color-mix(in srgb, var(--background-color-lighter) 50%, transparent);
background-color: color-mix(in srgb, var(--secondary-color-3) 50%, transparent);
}
&.active {
background-color: var(--background-color-lighter);
background-color: var(--secondary-color-3);
}
div.selection-label {
display: flex;
@ -116,8 +116,8 @@ searchbar {
padding: 0.1rem 0.4rem;
border-radius: var(--border-radius-small);
font-size: 0.9rem;
background-color: var(--secondary-color-darker);
color: var(--secondary-color);
background-color: var(--secondary-color-4);
color: var(--secondary-color-9);
}
}
@ -125,7 +125,7 @@ searchbar {
}
div.filter {
background-color: var(--background-color);
background-color: var(--secondary-color-1);
opacity: 0.5;
position: fixed;
top: 0;
@ -137,7 +137,7 @@ searchbar {
.input-wrapper {
color: var(--primary-color);
border: 1px solid var(--secondary-color);
border: 1px solid var(--secondary-color-9);
border-radius: var(--border-radius-small);
position: relative;
box-sizing: border-box;

View File

@ -84,9 +84,23 @@ $(document.body).content([
// Base Router
$('router').base('/').map([
// Home Page
$('route').id('posts').path('/').builder(() => new $PostGrid()),
$('route').id('posts').path(['/', '/posts']).builder(() => new $PostGrid()),
// Posts Page
$('route').id('posts').path('/posts?tags').builder(({query}) => new $PostGrid({tags: query.tags})),
$('route').id('posts').path('/posts?tags').builder(({query}) => {
const $postGrid = new $PostGrid({tags: query.tags});
return [
$('header').content([
$('h2').content('Posts'),
$('div').class('tags').self($div => {
query.tags.split('+').forEach(tag => {
$div.insert($('a').class('tag').content(decodeURIComponent(tag)).href(`posts?tags=${tag}`))
})
})
]),
$('div').class('no-post').content('No Posts').hide(true).self($div => $postGrid.on('noPost', () => $div.hide(false)).on('startLoad', () => $div.hide(true))),
$postGrid
]
}),
// Post Page
post_route,
// Login Page

View File

@ -6,12 +6,16 @@ route#login {
.login-container {
padding: 2rem;
border: 1px solid var(--secondary-color);
border: 1px solid var(--secondary-color-9);
border-radius: var(--border-radius-large);
display: flex;
flex-direction: column;
justify-content: center;
gap: 1rem;
max-width: 400px;
width: 100%;
box-sizing: border-box;
h1 {
margin: 0;
}
@ -20,7 +24,7 @@ route#login {
flex-direction: column;
gap: 0.5rem;
input {
width: 300px;
display: block;
}
}
}

View File

@ -139,17 +139,15 @@
width: 100%;
overflow: hidden;
span.property-value {
padding: 2px 4px;
background-color: var(--secondary-color-darker);
color: var(--secondary-color);
padding: 0.2rem 0.4rem;
background-color: var(--secondary-color-1);
color: var(--primary-color-dark);
border-radius: var(--border-radius-small);
justify-content: space-between;
flex-shrink: 1;
&:has(*) {
overflow: hidden;
padding: 0;
}
display: flex;
align-items: center;
overflow: hidden;
&:has(ion-icon) {
flex-shrink: 0;
@ -157,12 +155,12 @@
* {
display: block;
padding: 2px 4px;
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
flex-shrink: 1;
}
ion-icon {
font-size: 1rem;
padding: 4px;
@ -183,12 +181,11 @@
align-items: center;
a.tag-name {
word-break: break-word;
color: #d1d1ee;
text-decoration: none;
}
span.tag-post-count {
background-color: var(--secondary-color-darker);
color: var(--secondary-color);
background-color: var(--secondary-color-3);
color: var(--secondary-color-8);
padding: 0px 4px;
border-radius: var(--border-radius-small);
font-size: 12px;