search tags

loading placeholder items
This commit is contained in:
2025-07-03 21:54:29 -04:00
parent 2a0907cf0d
commit cf55a7d47b
9 changed files with 255 additions and 211 deletions

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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 {}
})}
}
},
}

View File

@@ -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 { }
}
}
}
};
}
}