-
- {{ rewindData.data.sphere.mostLovedPublisher.publisher.nick }}
-
-
- @{{ rewindData.data.sphere.mostLovedPublisher.publisher.name }}
-
-
-
- {{ rewindData.data.sphere.mostLovedPublisher.publisher.level }} Level
-
-
- {{ rewindData.data.sphere.mostLovedPublisher.upvoteCounts }} Upvotes
-
+
+
+
+
+
+ 最常出没的聊天室
+
+
+
+
{{
+ rewindData.data.sphere.mostMessagedChat.chat.name?.substring(
+ 0,
+ 1
+ )
+ }}
+
+
+ {{
+ rewindData.data.sphere.mostMessagedChat.chat.name
+ }}
+
+
+
+ 条消息
+
+
-
+
+
+
+
+
+ 最常联系的人
+
+
+
+
+
+
+ {{
+ rewindData.data.sphere.mostMessagedDirectChat.chat
+ .members[0]!.account.name || "Direct Message"
+ }}
+
+
+
+ 条消息
+
+
+
+
-
- {{ rewindData.data.sphere.mostLovedPublisher.publisher.bio }}
-
-
-
-
- Most Messaged Chat
-
-
- {{ rewindData.data.sphere.mostMessagedChat.name || 'Direct Message' }}
-
-
- Your most active conversation
-
-
+
+
💬
+
+ 一眼丁真,鉴定为
+ 纯纯的话唠
+
-
@@ -327,11 +469,16 @@
Share Your Year
- Capture this moment and share your Solar Network journey with friends!
+ Capture this moment and share your Solar Network journey
+ with friends!
-
+
@@ -346,10 +493,13 @@
-
+
What's Next?
- Keep creating, connecting, and exploring. Your 2026 rewind will be even more amazing!
+ Keep creating, connecting, and exploring. Your 2026 rewind
+ will be even more amazing!
@@ -365,23 +515,25 @@
import {
GlobeIcon,
MessageCircleIcon,
- UsersIcon,
+ MessageCircleHeartIcon,
HeartIcon,
StarIcon,
- ShieldIcon,
+ CalendarDaysIcon,
+ PencilLineIcon,
DownloadIcon,
- ShareIcon
+ ShareIcon,
+ PartyPopperIcon
} from "lucide-vue-next"
import { ref, onMounted, onUnmounted } from "vue"
import { DateTime } from "luxon"
import type {
SnRewind,
SnRewindMostCalledChat,
- SnRewindMostCalledAccount,
- SnRewindMostLovedPublisher
+ SnRewindChat,
+ SnRewindChatMember
} from "~/types/api"
-import CloudyRewind from "~/assets/images/cloudy-lamb-rewind.png";
+import CloudyRewind from "~/assets/images/cloudy-lamb-rewind.png"
const api = useSolarNetwork()
@@ -425,16 +577,19 @@ const fetchRewindData = async () => {
const setupScrollAnimations = () => {
const options = {
threshold: 0.1,
- rootMargin: '0px 0px -50px 0px'
+ rootMargin: "0px 0px -50px 0px"
}
- const createObserver = (element: HTMLElement, inViewRef: { value: boolean }) => {
+ const createObserver = (
+ element: HTMLElement,
+ inViewRef: { value: boolean }
+ ) => {
const observer = new IntersectionObserver((entries) => {
- entries.forEach(entry => {
+ entries.forEach((entry) => {
inViewRef.value = entry.isIntersecting
})
}, options)
-
+
if (element) {
observer.observe(element)
observers.push(observer)
@@ -456,7 +611,7 @@ onMounted(() => {
})
onUnmounted(() => {
- observers.forEach(observer => observer.disconnect())
+ observers.forEach((observer) => observer.disconnect())
})
// Helper methods
@@ -470,17 +625,17 @@ const getChatAvatar = (chat: SnRewindMostCalledChat) => {
return "/api/placeholder/48/48"
}
-const getAccountAvatar = (account: SnRewindMostCalledAccount) => {
+const getChatRoomAvatar = (item: SnRewindChat) => {
const apiBase = useSolarNetworkUrl()
- return account.profile?.picture
- ? `${apiBase}/drive/files/${account.profile.picture.id}`
+ return item.picture
+ ? `${apiBase}/drive/files/${item.picture.id}`
: "/api/placeholder/48/48"
}
-const getPublisherAvatar = (publisher: SnRewindMostLovedPublisher) => {
+const getChatMemberAvatar = (member: SnRewindChatMember) => {
const apiBase = useSolarNetworkUrl()
- return publisher.publisher?.picture
- ? `${apiBase}/drive/files/${publisher.publisher.picture.id}`
+ return member.account?.profile?.picture
+ ? `${apiBase}/drive/files/${member.account.profile.picture.id}`
: "/api/placeholder/64/64"
}
@@ -489,22 +644,6 @@ const downloadSummary = () => {
// Create a simple text summary for download
const summary = `
Solar Network Rewind ${rewindData.value?.year}
-
-Your Journey:
-- Total Posts: ${rewindData.value?.data.sphere.totalCount}
-- Upvotes Received: ${rewindData.value?.data.sphere.upvoteCounts}
-- Longest Check-in Streak: ${rewindData.value?.data.pass.maxCheckInStrike} days
-- Best Day: ${
- rewindData.value?.data.sphere.mostProductiveDay.postCount
- } posts on ${formatDate(rewindData.value?.data.sphere.mostProductiveDay.date ?? 'none')}
-
-Highlights:
-- Favorite Chat: ${rewindData.value?.data.sphere.mostCalledChat.name}
-- Top Connection: ${rewindData.value?.data.sphere.mostCalledAccounts[0]?.nick}
-- Loved Publisher: ${
- rewindData.value?.data.sphere.mostLovedPublisher.publisher.nick
- }
-
Generated on: ${new Date().toLocaleDateString()}
`
@@ -520,7 +659,7 @@ Generated on: ${new Date().toLocaleDateString()}
}
const shareOnSocial = () => {
- const text = `Just checked out my Solar Network Rewind ${rewindData.value?.year}! 🚀\n\nI made ${rewindData.value?.data.sphere.totalCount} posts and got ${rewindData.value?.data.sphere.upvoteCounts} upvotes. What was your highlight of the year?`
+ const text = `Just checked out my Solar Network Rewind ${rewindData.value?.year}! 🚀\n\nI made ${rewindData.value?.data.sphere.totalPostCount} posts and got ${rewindData.value?.data.sphere.totalUpvoteCount} upvotes. What was your highlight of the year?`
if (navigator.share) {
navigator.share({
@@ -535,8 +674,45 @@ const shareOnSocial = () => {
}
}
+// Helper methods for streak messages
+const getStreakMessage = (streak: number): string => {
+ if (streak >= 365) {
+ return "年度签到王"
+ } else if (streak >= 300) {
+ return "签到狂人"
+ } else if (streak >= 200) {
+ return "签到达人"
+ } else if (streak >= 100) {
+ return "签到高手"
+ } else if (streak >= 50) {
+ return "签到积极分子"
+ } else if (streak >= 20) {
+ return "签到新手"
+ } else {
+ return "继续签到"
+ }
+}
+
+const getStreakDescription = (streak: number): string => {
+ if (streak >= 365) {
+ return `连续签到 ${streak} 天,你就是 Solar Network 的签到传奇`
+ } else if (streak >= 300) {
+ return `连续签到 ${streak} 天,你的坚持让人佩服`
+ } else if (streak >= 200) {
+ return `连续签到 ${streak} 天,签到已经成为你的习惯`
+ } else if (streak >= 100) {
+ return `连续签到 ${streak} 天,你真的很用心在使用 Solar Network`
+ } else if (streak >= 50) {
+ return `连续签到 ${streak} 天,继续保持这个好习惯`
+ } else if (streak >= 20) {
+ return `连续签到 ${streak} 天,开始养成好习惯`
+ } else {
+ return `连续签到 ${streak} 天,每天签到让生活更有仪式感`
+ }
+}
+
useHead({
- title: "Your Solar Network Rewind",
+ title: "Solar Network Rewind 2025",
meta: [
{
name: "description",
@@ -559,10 +735,22 @@ useHead({
}
/* Staggered animation delays */
-.scroll-section:nth-child(1).animate-in { transition-delay: 0.1s; }
-.scroll-section:nth-child(2).animate-in { transition-delay: 0.2s; }
-.scroll-section:nth-child(3).animate-in { transition-delay: 0.3s; }
-.scroll-section:nth-child(4).animate-in { transition-delay: 0.4s; }
-.scroll-section:nth-child(5).animate-in { transition-delay: 0.5s; }
-.scroll-section:nth-child(6).animate-in { transition-delay: 0.6s; }
+.scroll-section:nth-child(1).animate-in {
+ transition-delay: 0.1s;
+}
+.scroll-section:nth-child(2).animate-in {
+ transition-delay: 0.2s;
+}
+.scroll-section:nth-child(3).animate-in {
+ transition-delay: 0.3s;
+}
+.scroll-section:nth-child(4).animate-in {
+ transition-delay: 0.4s;
+}
+.scroll-section:nth-child(5).animate-in {
+ transition-delay: 0.5s;
+}
+.scroll-section:nth-child(6).animate-in {
+ transition-delay: 0.6s;
+}
diff --git a/app/types/api/rewind.ts b/app/types/api/rewind.ts
index aef84db..f8f64fa 100644
--- a/app/types/api/rewind.ts
+++ b/app/types/api/rewind.ts
@@ -1,125 +1,122 @@
// Rewind data interfaces
-import type { SnCloudFile } from './post'
+import type { SnCloudFile } from "./post"
+import type { SnPublisher } from "./publisher"
+import type { SnAccount } from "./user"
-export interface SnRewindPassData {
- maxCheckInStrike: number;
+export interface SnRewindActiveData {
+ maxCheckInStreak: number
+ mostActiveDay: string
+ mostActiveWeekday: string
+ latestActiveTime: string
+ checkInCompleteness: number
}
export interface SnRewindMostCalledChat {
- id: string;
- name: string;
- type: number;
- description: string;
- picture: SnCloudFile | null;
- realmId: string | null;
- accountId: string;
- isPublic: boolean;
- isCommunity: boolean;
- background: SnCloudFile | null;
- createdAt: string;
- updatedAt: string;
- deletedAt: string | null;
+ id: string
+ name: string
+ type: number
+ description: string
+ picture: SnCloudFile | null
+ realmId: string | null
+ accountId: string
+ isPublic: boolean
+ isCommunity: boolean
+ background: SnCloudFile | null
+ createdAt: string
+ updatedAt: string
+ deletedAt: string | null
}
export interface SnRewindMostPopularPost {
- id: string;
- title: string;
- upvotes: number;
- viewsTotal: number;
- viewsUnique: number;
- createdAt: string;
- updatedAt: string;
- publishedAt: string;
+ id: string
+ title: string
+ upvotes: number
+ viewsTotal: number
+ viewsUnique: number
+ createdAt: string
+ updatedAt: string
+ publishedAt: string
}
export interface SnRewindMostProductiveDay {
- date: string;
- postCount: number;
-}
-
-export interface SnRewindMostCalledAccount {
- id: string;
- name: string;
- nick: string;
- profile: {
- id: string;
- bio: string;
- level: number;
- picture: SnCloudFile | null;
- background: SnCloudFile | null;
- createdAt: string;
- updatedAt: string;
- };
- createdAt: string;
- updatedAt: string;
+ date: string
+ postCount: number
}
export interface SnRewindMostLovedPublisher {
- publisher: {
- id: string;
- name: string;
- nick: string;
- bio: string;
- level: number;
- picture: SnCloudFile | null;
- background: SnCloudFile | null;
- createdAt: string;
- updatedAt: string;
- };
- upvoteCounts: number;
+ publisher: SnPublisher
+ upvoteCounts: number
}
-export interface SnRewindMostMessagedChat {
- id: string;
- name: string | null;
- type: number;
- members: SnRewindChatMember[];
- createdAt: string;
- updatedAt: string;
+export interface SnRewindChat {
+ id: string
+ name: string | null
+ type: number
+ members: SnRewindChatMember[]
+ picture: SnCloudFile | null
+ background: SnCloudFile | null
+ createdAt: string
+ updatedAt: string
+}
+
+export interface SnRewindCallSummary {
+ chat: SnRewindChat
+ duration: number
+}
+
+export interface SnRewindChatSummary {
+ chat: SnRewindChat
+ messageCounts: number
}
export interface SnRewindChatMember {
- id: string;
- nick: string | null;
- role: number;
- isBot: boolean;
+ id: string
+ nick: string | null
+ role: number
account: {
- id: string;
- name: string;
- nick: string;
+ id: string
+ name: string
+ nick: string
profile: {
- id: string;
- bio: string;
- level: number;
- picture: SnCloudFile | null;
- background: SnCloudFile | null;
- createdAt: string;
- updatedAt: string;
- };
- };
+ id: string
+ bio: string
+ level: number
+ picture: SnCloudFile | null
+ background: SnCloudFile | null
+ createdAt: string
+ updatedAt: string
+ }
+ }
}
-export interface SnRewindSphereData {
- totalCount: number;
- upvoteCounts: number;
- mostCalledChat: SnRewindMostCalledChat;
- mostPopularPost: SnRewindMostPopularPost;
- mostProductiveDay: SnRewindMostProductiveDay;
- mostCalledAccounts: SnRewindMostCalledAccount[];
- mostLovedPublisher: SnRewindMostLovedPublisher;
- mostMessagedChat: SnRewindMostMessagedChat;
+export interface SnRewindMostLovedAudience {
+ account: SnAccount
+ upvoteCounts: number
+}
+
+export interface SnRewindSocialData {
+ totalPostCount: number
+ totalUpvoteCount: number
+ mostCalledChat: SnRewindCallSummary
+ mostMessagedDirectChat: SnRewindChatSummary
+ mostPopularPost: SnRewindMostPopularPost
+ mostProductiveDay: SnRewindMostProductiveDay
+ mostCalledAccounts: SnAccount[]
+ mostLovedPublisher: SnRewindMostLovedPublisher
+ mostLovedAudience: SnRewindMostLovedAudience
+ mostMessagedChat: SnRewindChatSummary
}
export interface SnRewind {
- id: string;
- year: number;
- schemaVersion: number;
+ id: string
+ year: number
+ schemaVersion: number
data: {
- pass: SnRewindPassData;
- sphere: SnRewindSphereData;
- };
- accountId: string;
- createdAt: string;
- updatedAt: string;
- deletedAt: string | null;
+ pass: SnRewindActiveData
+ sphere: SnRewindSocialData
+ }
+ accountId: string
+ createdAt: string
+ updatedAt: string
+ deletedAt: string | null
}