search tags
loading placeholder items
This commit is contained in:
@@ -1,37 +1,37 @@
|
||||
[package]
|
||||
name = "aoba-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Amatsugu <khamraj@kaisei.app>"]
|
||||
edition = "2024"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { version = "0.6.0", features = ["router"] }
|
||||
serde = "1.0.219"
|
||||
serde_repr = "0.1.20"
|
||||
tonic = { version = "*", default-features = false, features = [
|
||||
"codegen",
|
||||
"prost",
|
||||
] }
|
||||
prost = "0.13"
|
||||
tonic-web-wasm-client = "0.7"
|
||||
web-sys = { version = "0.3.77", features = ["Storage", "Window"] }
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { version = "*", default-features = false, features = ["prost"] }
|
||||
|
||||
[features]
|
||||
default = ["web"]
|
||||
web = ["dioxus/web"]
|
||||
|
||||
[profile]
|
||||
|
||||
[profile.wasm-dev]
|
||||
inherits = "dev"
|
||||
opt-level = 1
|
||||
|
||||
[profile.server-dev]
|
||||
inherits = "dev"
|
||||
|
||||
[profile.android-dev]
|
||||
inherits = "dev"
|
||||
[package]
|
||||
name = "aoba-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Amatsugu <khamraj@kaisei.app>"]
|
||||
edition = "2024"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { version = "0.6.0", features = ["router"] }
|
||||
serde = "1.0.219"
|
||||
serde_repr = "0.1.20"
|
||||
tonic = { version = "*", default-features = false, features = [
|
||||
"codegen",
|
||||
"prost",
|
||||
] }
|
||||
prost = "0.13"
|
||||
tonic-web-wasm-client = "0.7"
|
||||
web-sys = { version = "0.3.77", features = ["Storage", "Window"] }
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { version = "*", default-features = false, features = ["prost"] }
|
||||
|
||||
[features]
|
||||
default = ["web"]
|
||||
web = ["dioxus/web"]
|
||||
|
||||
[profile]
|
||||
|
||||
[profile.wasm-dev]
|
||||
inherits = "dev"
|
||||
opt-level = 1
|
||||
|
||||
[profile.server-dev]
|
||||
inherits = "dev"
|
||||
|
||||
[profile.android-dev]
|
||||
inherits = "dev"
|
||||
|
||||
@@ -1,151 +1,154 @@
|
||||
@import "mixins";
|
||||
@import "colors";
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
background-color: $mainBGColor;
|
||||
color: $mainTextColor;
|
||||
box-sizing: border-box;
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-variation-settings: "wdth" 100;
|
||||
}
|
||||
|
||||
.stickyTop {
|
||||
top: 0;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main:has(#content) {
|
||||
display: grid;
|
||||
grid-template-columns: $navBarSize 1fr;
|
||||
grid-template-areas: "Nav Content";
|
||||
}
|
||||
|
||||
#content {
|
||||
grid-area: Content;
|
||||
overflow-x: hidden;
|
||||
padding: 10px;
|
||||
/* margin-left: $navBarSize; */
|
||||
}
|
||||
|
||||
$mediaItemSize: 300px;
|
||||
|
||||
.mediaGrid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin: 10px 0;
|
||||
|
||||
.mediaItem {
|
||||
width: $mediaItemSize;
|
||||
height: $mediaItemSize;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-columns: $mediaItemSize;
|
||||
grid-template-areas: "A";
|
||||
box-shadow: 0 0 2px #000;
|
||||
color: $mainTextColor;
|
||||
text-decoration: none;
|
||||
transition:
|
||||
transform 0.25s ease-out,
|
||||
box-shadow 0.25s ease-out;
|
||||
|
||||
> * {
|
||||
grid-area: A;
|
||||
}
|
||||
|
||||
img {
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
object-position: center;
|
||||
background-color: $invertTextColor;
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.info {
|
||||
align-self: end;
|
||||
backdrop-filter: blur(20px) brightness(0.5);
|
||||
transition: transform 0.25s ease-out;
|
||||
transform: translateY(100%);
|
||||
padding: 2px;
|
||||
|
||||
.name {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(110%) translateZ(2px);
|
||||
box-shadow: 0 0 8px #000;
|
||||
|
||||
.info {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#main:has(#centralModal) {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 100dvh;
|
||||
width: 100dvw;
|
||||
}
|
||||
|
||||
#centralModal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.notif {
|
||||
background-color: red;
|
||||
display: grid;
|
||||
grid-template-columns: 50px 1fr;
|
||||
height: 50px;
|
||||
border-radius: 20px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
|
||||
.icon {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.codeSelect {
|
||||
line-break: anywhere;
|
||||
white-space: pre-wrap;
|
||||
background-color: $featureColor;
|
||||
padding: 5px;
|
||||
user-select: all;
|
||||
}
|
||||
@import "mixins";
|
||||
@import "colors";
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
background-color: $mainBGColor;
|
||||
color: $mainTextColor;
|
||||
box-sizing: border-box;
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-variation-settings: "wdth" 100;
|
||||
}
|
||||
|
||||
.stickyTop {
|
||||
top: 0;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main:has(#content) {
|
||||
display: grid;
|
||||
grid-template-columns: $navBarSize 1fr;
|
||||
grid-template-areas: "Nav Content";
|
||||
}
|
||||
|
||||
#content {
|
||||
grid-area: Content;
|
||||
overflow-x: hidden;
|
||||
padding: 10px;
|
||||
/* margin-left: $navBarSize; */
|
||||
}
|
||||
|
||||
$mediaItemSize: 300px;
|
||||
|
||||
.mediaGrid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin: 10px 0;
|
||||
|
||||
.mediaItem {
|
||||
width: $mediaItemSize;
|
||||
height: $mediaItemSize;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-columns: $mediaItemSize;
|
||||
grid-template-areas: "A";
|
||||
box-shadow: 0 0 2px #000;
|
||||
color: $mainTextColor;
|
||||
text-decoration: none;
|
||||
transition:
|
||||
transform 0.25s ease-out,
|
||||
box-shadow 0.25s ease-out;
|
||||
|
||||
> * {
|
||||
grid-area: A;
|
||||
}
|
||||
|
||||
img {
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
object-position: center;
|
||||
background-color: $invertTextColor;
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.info {
|
||||
align-self: end;
|
||||
backdrop-filter: blur(20px) brightness(0.5);
|
||||
transition: transform 0.25s ease-out;
|
||||
transform: translateY(100%);
|
||||
padding: 2px;
|
||||
|
||||
.name {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(110%) translateZ(2px);
|
||||
box-shadow: 0 0 8px #000;
|
||||
|
||||
.info {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
&.placeholder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#main:has(#centralModal) {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 100dvh;
|
||||
width: 100dvw;
|
||||
}
|
||||
|
||||
#centralModal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.notif {
|
||||
background-color: red;
|
||||
display: grid;
|
||||
grid-template-columns: 50px 1fr;
|
||||
height: 50px;
|
||||
border-radius: 20px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
|
||||
.icon {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.codeSelect {
|
||||
line-break: anywhere;
|
||||
white-space: pre-wrap;
|
||||
background-color: $featureColor;
|
||||
padding: 5px;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
div {
|
||||
class: "mediaGrid",
|
||||
{result.items.iter().map(|itm| rsx!{
|
||||
MediaItem { item: itm.clone() }
|
||||
MediaItem { item: Some(itm.clone()) }
|
||||
})},
|
||||
}
|
||||
},
|
||||
@@ -68,9 +68,9 @@ pub fn MediaGrid(props: MediaGridProps) -> Element {
|
||||
None => rsx! {
|
||||
div{
|
||||
class: "mediaGrid",
|
||||
div {
|
||||
"Loading..."
|
||||
}
|
||||
{(0..50).map(|_| rsx!{
|
||||
MediaItem {}
|
||||
})}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,26 +4,41 @@ use crate::{HOST, rpc::aoba::MediaModel};
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
pub struct MediaItemProps {
|
||||
pub item: MediaModel,
|
||||
pub item: Option<MediaModel>,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn MediaItem(props: MediaItemProps) -> Element {
|
||||
let mtype = props.item.media_type().as_str_name();
|
||||
let filename = props.item.file_name;
|
||||
let id = props.item.media_id.unwrap().value;
|
||||
if let Some(item) = props.item {
|
||||
let mtype = item.media_type().as_str_name();
|
||||
let filename = item.file_name;
|
||||
let id = item.media_id.unwrap().value;
|
||||
|
||||
let src = format!("{HOST}/m/thumb/{id}");
|
||||
rsx! {
|
||||
a { class: "mediaItem", href: "{HOST}/m/{id}", target: "_blank",
|
||||
img { src }
|
||||
span { class: "info",
|
||||
span { class: "name", "{filename}" }
|
||||
span { class: "details",
|
||||
span { "{mtype}" }
|
||||
span { "{props.item.view_count}" }
|
||||
let src = format!("{HOST}/m/thumb/{id}");
|
||||
return rsx! {
|
||||
a { class: "mediaItem", href: "{HOST}/m/{id}", target: "_blank",
|
||||
img { src }
|
||||
span { class: "info",
|
||||
span { class: "name", "{filename}" }
|
||||
span { class: "details",
|
||||
span { "{mtype}" }
|
||||
span { "{item.view_count}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return rsx! {
|
||||
div { class: "mediaItem placeholder",
|
||||
img { },
|
||||
span { class: "info",
|
||||
span { class: "name" }
|
||||
span { class: "details",
|
||||
span { }
|
||||
span { }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user