mirror of
https://github.com/RhenCloud/Cloud-Home.git
synced 2026-01-22 17:39:07 +08:00
Compare commits
3 Commits
53685b1531
...
20eebcca4f
| Author | SHA1 | Date | |
|---|---|---|---|
| 20eebcca4f | |||
| f9e624d48e | |||
| 6edb6af6ee |
@@ -9,14 +9,7 @@
|
|||||||
class="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/10 backdrop-blur-sm border border-white/10 text-text-primary text-sm font-medium transition-all duration-200 hover:bg-primary/20 hover:border-primary/40 hover:text-primary hover:-translate-y-1"
|
class="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/10 backdrop-blur-sm border border-white/10 text-text-primary text-sm font-medium transition-all duration-200 hover:bg-primary/20 hover:border-primary/40 hover:text-primary hover:-translate-y-1"
|
||||||
>
|
>
|
||||||
<span v-if="iconFor(link)" class="inline-flex items-center justify-center w-5 h-5">
|
<span v-if="iconFor(link)" class="inline-flex items-center justify-center w-5 h-5">
|
||||||
<i v-if="iconFor(link).fa" :class="iconFor(link).fa" />
|
<Icon v-if="iconFor(link).name" :name="iconFor(link).name" width="20" height="20" />
|
||||||
<NuxtImg
|
|
||||||
v-else
|
|
||||||
:src="iconFor(link).src"
|
|
||||||
:alt="link.name"
|
|
||||||
loading="lazy"
|
|
||||||
class="w-full h-full"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
<span>{{ link.name }}</span>
|
<span>{{ link.name }}</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
@@ -26,7 +19,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted } from "vue";
|
|
||||||
defineProps({
|
defineProps({
|
||||||
links: {
|
links: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@@ -35,44 +27,31 @@ defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
bilibili: "fa-brands fa-bilibili",
|
bilibili: "simple-icons:bilibili",
|
||||||
github: "fa-brands fa-github",
|
github: "simple-icons:github",
|
||||||
blog: "fa-solid fa-rss",
|
blog: "fa6-solid:book",
|
||||||
email: "fa-solid fa-envelope",
|
email: "fa6-solid:envelope",
|
||||||
mail: "fa-solid fa-envelope",
|
mail: "fa6-solid:envelope",
|
||||||
telegram: "fa-brands fa-telegram",
|
telegram: "simple-icons:telegram",
|
||||||
twitter: "fa-brands fa-x-twitter",
|
twitter: "simple-icons:twitter",
|
||||||
x: "fa-brands fa-x-twitter",
|
x: "simple-icons:x",
|
||||||
linkedin: "fa-brands fa-linkedin",
|
linkedin: "simple-icons:linkedin",
|
||||||
youtube: "fa-brands fa-youtube",
|
youtube: "simple-icons:youtube",
|
||||||
facebook: "fa-brands fa-facebook",
|
facebook: "simple-icons:facebook",
|
||||||
instagram: "fa-brands fa-instagram",
|
instagram: "simple-icons:instagram",
|
||||||
reddit: "fa-brands fa-reddit",
|
reddit: "simple-icons:reddit",
|
||||||
discord: "fa-brands fa-discord",
|
discord: "simple-icons:discord",
|
||||||
weibo: "fa-brands fa-weibo",
|
weibo: "simple-icons:sinaweibo",
|
||||||
zhihu: "fa-brands fa-zhihu",
|
zhihu: "simple-icons:zhihu",
|
||||||
wechat: "fa-brands fa-weixin",
|
wechat: "simple-icons:wechat",
|
||||||
weixin: "fa-brands fa-weixin",
|
weixin: "simple-icons:wechat",
|
||||||
qq: "fa-brands fa-qq",
|
qq: "simple-icons:qq",
|
||||||
};
|
};
|
||||||
|
|
||||||
const iconFor = (link) => {
|
const iconFor = (link) => {
|
||||||
const key = (link.name || "").toLowerCase();
|
const key = (link.name || "").toLowerCase();
|
||||||
if (iconMap[key]) return { fa: iconMap[key] };
|
if (iconMap[key]) return { name: iconMap[key] };
|
||||||
if (link.icon) return { src: link.icon };
|
if (link.icon) return { src: link.icon };
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
const id = "fa-cdn";
|
|
||||||
if (document.getElementById(id)) return;
|
|
||||||
const link = document.createElement("link");
|
|
||||||
link.id = id;
|
|
||||||
link.rel = "stylesheet";
|
|
||||||
link.href =
|
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css?font-display=swap";
|
|
||||||
link.crossOrigin = "anonymous";
|
|
||||||
link.referrerPolicy = "no-referrer";
|
|
||||||
document.head.appendChild(link);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -79,15 +79,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed } from "vue";
|
import { ref, onMounted, computed } from "vue";
|
||||||
|
import siteConfig from "~/config/siteConfig";
|
||||||
|
|
||||||
const props = defineProps({
|
const wakapi = siteConfig.wakapi;
|
||||||
wakatime: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: () => ({ languages: [] }),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const wakatime = props.wakatime;
|
|
||||||
|
|
||||||
const weeklyData = ref(null);
|
const weeklyData = ref(null);
|
||||||
const allTimeData = ref(null);
|
const allTimeData = ref(null);
|
||||||
@@ -123,65 +117,45 @@ const formatTime = (seconds) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchWakatimeData = async () => {
|
const fetchWakatimeData = async () => {
|
||||||
if (!wakatime.enable) return;
|
if (!wakapi.enable) {
|
||||||
|
console.warn("Wakatime is disabled in siteConfig.");
|
||||||
try {
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
if (wakatime.apiUrl && wakatime.apiUrl !== "https://wakatime.com/api/v1") {
|
|
||||||
params.append("apiUrl", wakatime.apiUrl);
|
|
||||||
}
|
|
||||||
const url = `/api/wakatime${params.toString() ? `?${params.toString()}` : ""}`;
|
|
||||||
console.log("Fetching Wakatime data from:", url);
|
|
||||||
const response = await fetch(url);
|
|
||||||
console.log("Response status:", response.status);
|
|
||||||
console.log("Response headers:", Object.fromEntries(response.headers.entries()));
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
console.log("Wakatime data:", data);
|
|
||||||
weeklyData.value = data.weekly;
|
|
||||||
allTimeData.value = data.allTime;
|
|
||||||
statusData.value = data.status;
|
|
||||||
} else {
|
|
||||||
const errorText = await response.text();
|
|
||||||
console.error("API Error:", response.status, errorText);
|
|
||||||
if (response.status === 500 && errorText.includes("Wakatime API Key not configured")) {
|
|
||||||
console.warn("Wakatime API Key not configured - hiding component");
|
|
||||||
showComponent.value = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error(`API returned ${response.status}: ${errorText}`);
|
|
||||||
|
const apiUrl = wakapi.apiUrl || "https://wakatime.com/api/v1";
|
||||||
|
const username = wakapi.username;
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
console.error("Wakatime username is not configured.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [weeklyStatsResponse, allTimeStatsResponse, statusResponse] = await Promise.all([
|
||||||
|
fetch(`${apiUrl}/users/${username}/stats/last_7_days`),
|
||||||
|
fetch(`${apiUrl}/users/${username}/stats`),
|
||||||
|
fetch(`${apiUrl}/users/${username}/status`),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (weeklyStatsResponse.ok) {
|
||||||
|
weeklyData.value = await weeklyStatsResponse.json();
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch weekly stats:", weeklyStatsResponse.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allTimeStatsResponse.ok) {
|
||||||
|
allTimeData.value = await allTimeStatsResponse.json();
|
||||||
|
} else {
|
||||||
|
console.warn("All-time stats not available:", allTimeStatsResponse.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusResponse.ok) {
|
||||||
|
statusData.value = await statusResponse.json();
|
||||||
|
} else {
|
||||||
|
console.warn("Status data not available:", statusResponse.status);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch Wakatime data:", error);
|
console.error("Error fetching Wakatime data:", error);
|
||||||
// 在开发环境中,如果 API 不可用,设置一些示例数据
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
console.log("Using mock data for development");
|
|
||||||
weeklyData.value = {
|
|
||||||
total_seconds: 36000,
|
|
||||||
daily_average: 5142,
|
|
||||||
days_including_holidays: 7,
|
|
||||||
languages: [
|
|
||||||
{ name: "TypeScript", percent: 45.2, total_seconds: 16272 },
|
|
||||||
{ name: "Vue", percent: 30.1, total_seconds: 10836 },
|
|
||||||
{ name: "JavaScript", percent: 15.3, total_seconds: 5508 },
|
|
||||||
{ name: "Python", percent: 9.4, total_seconds: 3384 },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
allTimeData.value = {
|
|
||||||
total_seconds: 864000,
|
|
||||||
daily_average: 2800,
|
|
||||||
days_including_holidays: 308,
|
|
||||||
languages: [
|
|
||||||
{ name: "JavaScript", percent: 35.2, total_seconds: 304128 },
|
|
||||||
{ name: "TypeScript", percent: 28.1, total_seconds: 242688 },
|
|
||||||
{ name: "Python", percent: 20.3, total_seconds: 175392 },
|
|
||||||
{ name: "Vue", percent: 10.1, total_seconds: 87296 },
|
|
||||||
{ name: "CSS", percent: 6.3, total_seconds: 54432 },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
statusData.value = { is_coding: false };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const siteConfig = {
|
|||||||
profile: {
|
profile: {
|
||||||
name: "RhenCloud",
|
name: "RhenCloud",
|
||||||
title: "I'm RhenCloud.",
|
title: "I'm RhenCloud.",
|
||||||
avatar: "/avatar.webp", // public/avatar.webp
|
avatar: "/avatar-1.webp", // public/avatar.webp
|
||||||
bio: "趁世界还未重启之前 约一次爱恋",
|
bio: "趁世界还未重启之前 约一次爱恋",
|
||||||
email: "i@rhen.cloud",
|
email: "i@rhen.cloud",
|
||||||
birthday: "2010-03-28",
|
birthday: "2010-03-28",
|
||||||
@@ -17,6 +17,7 @@ const siteConfig = {
|
|||||||
{ name: "Telegram", url: "https://t.me/RhenCloud" },
|
{ name: "Telegram", url: "https://t.me/RhenCloud" },
|
||||||
{ name: "Bilibili", url: "https://space.bilibili.com/1502883335" },
|
{ name: "Bilibili", url: "https://space.bilibili.com/1502883335" },
|
||||||
{ name: "Blog", url: "https://blog.rhen.cloud" },
|
{ name: "Blog", url: "https://blog.rhen.cloud" },
|
||||||
|
{ name: "Twitter", url: "https://x.com/RhenCloud75" },
|
||||||
],
|
],
|
||||||
|
|
||||||
github: {
|
github: {
|
||||||
@@ -32,9 +33,13 @@ const siteConfig = {
|
|||||||
|
|
||||||
siteMeta: {
|
siteMeta: {
|
||||||
title: "RhenCloud",
|
title: "RhenCloud",
|
||||||
|
description: "RhenCloud的个人主页,分享技术、生活、兴趣。",
|
||||||
|
keywords: ["Technology", "Blog", "Development", "Programming"],
|
||||||
|
author: "RhenCloud",
|
||||||
url: "https://rhen.cloud",
|
url: "https://rhen.cloud",
|
||||||
icon: "/favicon.svg", // public/favicon.svg
|
favicon: "/favicon.svg", // public/favicon.svg
|
||||||
startDate: "2025-12-06",
|
startDate: "2025-12-06",
|
||||||
|
lang: "zh-CN",
|
||||||
},
|
},
|
||||||
|
|
||||||
appearance: {
|
appearance: {
|
||||||
@@ -80,9 +85,10 @@ const siteConfig = {
|
|||||||
apiBase: "https://api.umami.is",
|
apiBase: "https://api.umami.is",
|
||||||
},
|
},
|
||||||
|
|
||||||
wakatime: {
|
wakapi: {
|
||||||
enable: true,
|
enable: false,
|
||||||
apiUrl: "https://wakapi.rhen.cloud/api/v1",
|
apiUrl: "https://wakapi.rhen.cloud/api/v1",
|
||||||
|
username: "RhenCloud",
|
||||||
},
|
},
|
||||||
|
|
||||||
skills: [
|
skills: [
|
||||||
|
|||||||
@@ -5,18 +5,7 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: "2025-12-12",
|
compatibilityDate: "2025-12-12",
|
||||||
srcDir: "app/",
|
srcDir: "app/",
|
||||||
modules: ["@nuxt/image", "@nuxt/eslint", "@nuxtjs/sitemap"],
|
modules: ["@nuxt/image", "@nuxt/eslint", "@nuxtjs/sitemap", "@nuxt/icon", "@nuxtjs/seo"],
|
||||||
|
|
||||||
// eslint: {
|
|
||||||
// config: {
|
|
||||||
// extends: ["plugin:nuxt/recommended", "prettier"],
|
|
||||||
// plugins: ["prettier"],
|
|
||||||
// rules: {
|
|
||||||
// "prettier/prettier": "error",
|
|
||||||
// },
|
|
||||||
// stylistic: true
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
|
|
||||||
// 禁用 Vue Router 的非关键警告
|
// 禁用 Vue Router 的非关键警告
|
||||||
vue: {
|
vue: {
|
||||||
@@ -32,11 +21,6 @@ export default defineNuxtConfig({
|
|||||||
plugins: [tailwindcss()],
|
plugins: [tailwindcss()],
|
||||||
},
|
},
|
||||||
|
|
||||||
site: {
|
|
||||||
url: siteConfig.siteMeta.url,
|
|
||||||
title: siteConfig.siteMeta.title,
|
|
||||||
},
|
|
||||||
|
|
||||||
routeRules: {
|
routeRules: {
|
||||||
"/": { prerender: true },
|
"/": { prerender: true },
|
||||||
"/about": { isr: 3600 },
|
"/about": { isr: 3600 },
|
||||||
@@ -47,32 +31,26 @@ export default defineNuxtConfig({
|
|||||||
|
|
||||||
app: {
|
app: {
|
||||||
head: {
|
head: {
|
||||||
|
charset: "utf-8",
|
||||||
|
viewport: "width=device-width,initial-scale=1,maximum-scale=5",
|
||||||
title: siteConfig.siteMeta.title,
|
title: siteConfig.siteMeta.title,
|
||||||
|
titleTemplate: `%s - ${siteConfig.siteMeta.title}`,
|
||||||
|
meta: [
|
||||||
|
{ name: "author", content: siteConfig.siteMeta.author },
|
||||||
|
{ name: "language", content: "zh-CN" },
|
||||||
|
{ name: "description", content: siteConfig.siteMeta.description },
|
||||||
|
],
|
||||||
link: [
|
link: [
|
||||||
{ rel: "icon", href: siteConfig.siteMeta.icon },
|
{ rel: "icon", href: siteConfig.siteMeta.favicon, type: "image/svg+xml" },
|
||||||
// Font Awesome CDN 预加载和优化
|
{ rel: "canonical", href: siteConfig.siteMeta.url },
|
||||||
{
|
{ rel: "alternate", hreflang: siteConfig.siteMeta.lang, href: siteConfig.siteMeta.url },
|
||||||
rel: "preload",
|
{ rel: "dns-prefetch", href: siteConfig.siteMeta.url },
|
||||||
as: "style",
|
{ rel: "preconnect", href: siteConfig.siteMeta.url },
|
||||||
href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css?font-display=swap",
|
{ rel: "icon", href: siteConfig.siteMeta.favicon },
|
||||||
crossorigin: "anonymous",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: "preload",
|
|
||||||
as: "font",
|
|
||||||
href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.woff2?font-display=swap",
|
|
||||||
type: "font/woff2",
|
|
||||||
crossorigin: "anonymous",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: "preload",
|
|
||||||
as: "font",
|
|
||||||
href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-brands-400.woff2?font-display=swap",
|
|
||||||
type: "font/woff2",
|
|
||||||
crossorigin: "anonymous",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
pageTransition: { name: "page", mode: "out-in" },
|
||||||
|
layoutTransition: { name: "layout", mode: "out-in" },
|
||||||
},
|
},
|
||||||
|
|
||||||
nitro: {
|
nitro: {
|
||||||
@@ -91,9 +69,11 @@ export default defineNuxtConfig({
|
|||||||
senderEmail: process.env.SENDER_EMAIL ?? "",
|
senderEmail: process.env.SENDER_EMAIL ?? "",
|
||||||
adminEmail: process.env.ADMIN_EMAIL ?? "",
|
adminEmail: process.env.ADMIN_EMAIL ?? "",
|
||||||
smtpSecure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === "true" : undefined,
|
smtpSecure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === "true" : undefined,
|
||||||
wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "",
|
|
||||||
wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1",
|
|
||||||
githubToken: process.env.NUXT_PUBLIC_GITHUB_TOKEN ?? "",
|
githubToken: process.env.NUXT_PUBLIC_GITHUB_TOKEN ?? "",
|
||||||
umamiApiKey: process.env.UMAMI_API_KEY ?? "",
|
umamiApiKey: process.env.UMAMI_API_KEY ?? "",
|
||||||
|
public: {
|
||||||
|
wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "",
|
||||||
|
wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
29
package.json
29
package.json
@@ -1,6 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "cloud-home",
|
"name": "cloud-home",
|
||||||
"private": false,
|
"author": {
|
||||||
|
"name": "RhenCloud",
|
||||||
|
"email": "i@rhen.cloud",
|
||||||
|
"url": "https://rhen.cloud"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt dev",
|
"dev": "nuxt dev",
|
||||||
@@ -15,23 +20,27 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@giscus/vue": "^3.1.1",
|
"@giscus/vue": "^3.1.1",
|
||||||
"@jaseeey/vue-umami-plugin": "^1.4.0",
|
"@jaseeey/vue-umami-plugin": "^1.4.0",
|
||||||
|
"@nuxt/icon": "^2.2.0",
|
||||||
"@nuxt/image": "2.0.0",
|
"@nuxt/image": "2.0.0",
|
||||||
"@nuxtjs/sitemap": "^7.5.0",
|
"@nuxtjs/icon": "^2.6.0",
|
||||||
"nodemailer": "^7.0.11",
|
"@nuxtjs/seo": "3.3.0",
|
||||||
|
"@nuxtjs/sitemap": "^7.5.2",
|
||||||
|
"nodemailer": "^7.0.12",
|
||||||
"nuxt": "^4.2.2",
|
"nuxt": "^4.2.2",
|
||||||
"vite-tsconfig-paths": "^6.0.1"
|
"vite-tsconfig-paths": "^6.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@iconify-json/fa6-brands": "^1.2.6",
|
||||||
|
"@iconify-json/simple-icons": "^1.2.66",
|
||||||
"@nuxt/eslint": "1.12.1",
|
"@nuxt/eslint": "1.12.1",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@types/node": "^24.10.1",
|
"@types/nodemailer": "^7.0.5",
|
||||||
"@types/nodemailer": "^7.0.4",
|
"@typescript-eslint/parser": "^8.53.0",
|
||||||
"@typescript-eslint/parser": "^8.50.0",
|
"autoprefixer": "^10.4.23",
|
||||||
"autoprefixer": "^10.4.22",
|
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^9.39.2",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-prettier": "^5.5.4",
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
"prettier": "^3.7.4",
|
"prettier": "^3.8.0",
|
||||||
"prettier-eslint": "^16.4.2",
|
"prettier-eslint": "^16.4.2",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
|
|||||||
1808
pnpm-lock.yaml
generated
1808
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,2 @@
|
|||||||
onlyBuiltDependencies:
|
ignoredBuiltDependencies:
|
||||||
- esbuild
|
- core-js
|
||||||
- sharp@0.34.5
|
|
||||||
|
|||||||
BIN
public/avatar-1.webp
Normal file
BIN
public/avatar-1.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 587 KiB |
Reference in New Issue
Block a user