Skip to content

Commit b07790e

Browse files
committed
feat: add package updated time display to plugin page
- Add package_updated_at to plugin view - Display relative time (5h ago, 2d ago, etc.) next to version number
1 parent 5866d1f commit b07790e

File tree

2 files changed

+107
-12
lines changed

2 files changed

+107
-12
lines changed

src/pages/plugin/plugin.scss

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
gap: 20px;
1313
align-items: start;
1414
margin-bottom: 24px;
15+
1516
.plugin-icon {
1617
width: 80px;
1718
height: 80px;
@@ -20,17 +21,20 @@
2021
background-repeat: no-repeat;
2122
background-size: contain;
2223
}
24+
2325
.plugin-info {
2426
.title-wrapper {
2527
display: flex;
2628
align-items: center;
2729
flex-wrap: wrap;
2830
gap: 16px;
2931
margin-bottom: 8px;
32+
3033
.plugin-name {
3134
font-size: 24px;
3235
margin-bottom: 0;
3336
}
37+
3438
.source-indicator {
3539
display: flex;
3640
align-items: center;
@@ -45,36 +49,48 @@
4549
transition: all 0.3s ease;
4650
border: 1px solid rgba(255, 255, 255, 0.1);
4751
text-decoration: none;
52+
4853
&:hover {
4954
background-color: rgba(0, 0, 0, 0.5);
5055
transform: translateY(-1px);
5156
}
57+
5258
.icon {
5359
color: var(--primary-text-color);
5460
font-size: 14px;
5561
}
5662
}
5763
}
64+
5865
.plugin-meta {
5966
display: flex;
6067
gap: 16px;
6168
flex-wrap: wrap;
6269
color: color-mix(in srgb, var(--primary-text-color) 60%, transparent);
6370
font-size: 14px;
6471
margin-bottom: 12px;
72+
6573
.author-name {
6674
display: inline-flex;
6775
align-items: center;
6876
gap: 4px;
77+
6978
a {
7079
text-decoration: none;
7180
color: inherit;
7281
}
7382
}
83+
7484
.verified-tick {
7585
color: #3b82f6;
7686
font-size: 16px;
7787
}
88+
89+
.version-updated {
90+
opacity: 0.6;
91+
font-size: 0.8em;
92+
margin-left: 4px;
93+
}
7894
}
7995

8096
.metrics-row {
@@ -88,10 +104,12 @@
88104
display: flex;
89105
align-items: center;
90106
gap: 4px;
107+
91108
.metric-value {
92109
color: var(--primary-text-color);
93110
font-weight: 500;
94111
}
112+
95113
.rating-value {
96114
padding: 2px 8px;
97115
border-radius: 12px;
@@ -114,6 +132,7 @@
114132
}
115133
}
116134
}
135+
117136
.keywords {
118137
display: flex;
119138
gap: 6px;
@@ -122,21 +141,19 @@
122141
position: relative;
123142

124143
.keyword {
125-
background: color-mix(
126-
in srgb,
127-
var(--link-text-color) 10%,
128-
transparent
129-
);
144+
background: color-mix(in srgb,
145+
var(--link-text-color) 10%,
146+
transparent);
130147
color: var(--link-text-color);
131148
padding: 6px 10px;
132149
border-radius: 12px;
133150
font-size: 13px;
134151
transition: all 0.2s;
135-
border: 1px solid
136-
color-mix(in srgb, var(--link-text-color) 25%, transparent);
152+
border: 1px solid color-mix(in srgb, var(--link-text-color) 25%, transparent);
137153
}
138154
}
139155
}
156+
140157
.action-buttons {
141158
display: flex;
142159
gap: 8px;
@@ -164,10 +181,12 @@
164181
display: inline-flex;
165182
align-items: center;
166183
gap: 6px;
184+
167185
&:hover {
168186
transform: translateY(-1px);
169187
}
170188
}
189+
171190
.btn-install {
172191
background: var(--button-background-color);
173192
color: white;
@@ -182,12 +201,14 @@
182201
background-color: var(--danger-color) !important;
183202
color: white;
184203
}
204+
185205
.btn-secondary {
186206
background: var(--primary-color);
187207
color: var(--primary-text-color);
188-
shadow: 0 0 10px var(--box-shadow-color);
208+
box-shadow: 0 0 10px var(--box-shadow-color);
189209
}
190210
}
211+
191212
.more-info-small {
192213
text-align: center;
193214
font-style: italic;
@@ -231,6 +252,7 @@
231252
width: calc(100% - 10px);
232253
display: block;
233254
user-select: text;
255+
234256
div {
235257
background: var(--primary-color);
236258
}
@@ -279,17 +301,20 @@
279301
}
280302
}
281303
}
304+
282305
#changelog {
283306
.no-changelog {
284307
text-align: center;
285308
padding: 2rem;
286309
color: color-mix(in srgb, var(--primary-text-color) 60%, transparent);
310+
287311
i {
288312
font-size: 3rem;
289313
margin-bottom: 1rem;
290314
opacity: 0.7;
291315
display: block;
292316
}
317+
293318
p {
294319
margin: 0.5rem 0;
295320
}
@@ -309,6 +334,7 @@
309334
top: 20px;
310335
right: 20px;
311336
}
337+
312338
.title-wrapper,
313339
.plugin-meta,
314340
.metrics-row,
@@ -333,6 +359,7 @@
333359
}
334360
}
335361
}
362+
336363
.reviews-container {
337364
position: fixed;
338365
display: flex;
@@ -450,4 +477,4 @@
450477
}
451478
}
452479
}
453-
}
480+
}

src/pages/plugin/plugin.view.js

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default (props) => {
2727
author_verified: authorVerified,
2828
author_github: authorGithub,
2929
comment_count: commentCount,
30+
package_updated_at: packageUpdatedAt,
3031
} = props;
3132

3233
let rating = "unrated";
@@ -42,6 +43,48 @@ export default (props) => {
4243
rating = `${Math.round((votesUp / (votesUp + votesDown)) * 100)}%`;
4344
}
4445

46+
const formatUpdatedDate = (dateString) => {
47+
if (!dateString) return null;
48+
49+
const date = new Date(dateString);
50+
const now = new Date();
51+
const diffTime = now - date;
52+
53+
if (diffTime < 0) return null;
54+
55+
const diffSeconds = Math.floor(diffTime / 1000);
56+
const diffMinutes = Math.floor(diffSeconds / 60);
57+
const diffHours = Math.floor(diffMinutes / 60);
58+
const diffDays = Math.floor(diffHours / 24);
59+
const diffWeeks = Math.floor(diffDays / 7);
60+
const diffMonths = Math.floor(diffDays / 30);
61+
const diffYears = Math.floor(diffDays / 365);
62+
63+
if (diffSeconds < 60) {
64+
return "just now";
65+
} else if (diffMinutes < 60) {
66+
return `${diffMinutes}m ago`;
67+
} else if (diffHours < 24) {
68+
return `${diffHours}h ago`;
69+
} else if (diffDays === 1) {
70+
return "yesterday";
71+
} else if (diffDays < 7) {
72+
return `${diffDays}d ago`;
73+
} else if (diffWeeks === 1) {
74+
return "1w ago";
75+
} else if (diffDays < 30) {
76+
return `${diffWeeks}w ago`;
77+
} else if (diffMonths === 1) {
78+
return "1mo ago";
79+
} else if (diffDays < 365) {
80+
return `${diffMonths}mo ago`;
81+
} else if (diffYears === 1) {
82+
return "1y ago";
83+
} else {
84+
return `${diffYears}y ago`;
85+
}
86+
};
87+
4588
return (
4689
<div className="main" id="plugin">
4790
<div className="plugin-header">
@@ -62,7 +105,11 @@ export default (props) => {
62105
<div className="plugin-meta">
63106
<span className="meta-item">
64107
<i className="licons tag" style={{ fontSize: "12px" }}></i>
65-
<Version {...props} />
108+
<Version
109+
{...props}
110+
packageUpdatedAt={packageUpdatedAt}
111+
formatUpdatedDate={formatUpdatedDate}
112+
/>
66113
</span>
67114
<span className="meta-item author-name">
68115
<i className="icon person"></i>
@@ -307,11 +354,32 @@ function Buttons({
307354
);
308355
}
309356

310-
function Version({ currentVersion, version }) {
311-
if (!currentVersion) return <span>v{version}</span>;
357+
function Version({
358+
currentVersion,
359+
version,
360+
packageUpdatedAt,
361+
formatUpdatedDate,
362+
}) {
363+
const updatedText =
364+
formatUpdatedDate && packageUpdatedAt
365+
? formatUpdatedDate(packageUpdatedAt)
366+
: null;
367+
368+
if (!currentVersion) {
369+
return (
370+
<span>
371+
v{version}
372+
{updatedText && (
373+
<span className="version-updated">({updatedText})</span>
374+
)}
375+
</span>
376+
);
377+
}
378+
312379
return (
313380
<span>
314381
v{currentVersion}&nbsp;&#8594;&nbsp;v{version}
382+
{updatedText && <span className="version-updated">({updatedText})</span>}
315383
</span>
316384
);
317385
}

0 commit comments

Comments
 (0)