-
Notifications
You must be signed in to change notification settings - Fork 326
Expand file tree
/
Copy pathThreadCard.svelte
More file actions
119 lines (104 loc) · 3.84 KB
/
Copy pathThreadCard.svelte
File metadata and controls
119 lines (104 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<script lang="ts">
import { highlight } from '$lib/actions/highlight';
import type { DiscordThread } from './types';
import { sanitizeContent } from '$routes/threads/helpers';
export let thread: DiscordThread;
export let query: string;
$: highlightTerms = query?.split(' ') ?? [];
$: isResolved = thread.is_resolved || /\[(solved|resolved|closed|fixed)\]/i.test(thread.title);
function timeAgo(dateStr: string): string {
const diff = (Date.now() - new Date(dateStr).getTime()) / 1000;
const formatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
if (diff < 3600) return formatter.format(-Math.floor(diff / 60), 'minute');
if (diff < 86400) return formatter.format(-Math.floor(diff / 3600), 'hour');
if (diff < 2592000) return formatter.format(-Math.floor(diff / 86400), 'day');
if (diff < 31536000) return formatter.format(-Math.floor(diff / 2592000), 'month');
return formatter.format(-Math.floor(diff / 31536000), 'year');
}
</script>
{#key highlightTerms}
<a href="/threads/{thread.discord_id}" class="web-card is-normal has-border-gradient thread">
<div class="flex min-w-0 gap-2">
<h3
class="text-main-body text-primary min-w-0 flex-1 font-medium"
use:highlight={highlightTerms}
>
{thread.title}
</h3>
<!-- <time class="text-caption ml-auto">12 Jan, 2023</time> -->
</div>
<p
class="web-main-body-500 u-margin-block-start-4 u-break-word min-w-0"
use:highlight={highlightTerms}
>
{sanitizeContent(thread.content)}
</p>
<div class="mt-4 flex min-w-0 flex-wrap justify-between gap-4">
<ul class="flex min-w-0 flex-wrap gap-2">
{#if isResolved}
<li class="min-w-0">
<div class="web-tag tag-resolved truncate">
<span class="web-icon-check"></span>
Resolved
</div>
</li>
{/if}
{#each thread.tags ?? [] as tag, index (tag + index)}
<li class="min-w-0">
<div class="web-tag truncate">{tag}</div>
</li>
{/each}
</ul>
<div class="flex shrink-0 items-center gap-3">
<div
class="web-icon-button is-more-content web-u-pointer-events-none flex items-center"
aria-label="Replies"
>
<span class="web-icon-message web-u-font-size-16" aria-hidden="true"></span>
<span class="text-caption font-inter">{thread.message_count}</span>
</div>
{#if thread.last_activity}
<span class="text-caption">{timeAgo(thread.last_activity)}</span>
{/if}
</div>
</div>
</a>
{/key}
<style lang="scss">
.web-card {
padding: 1.25rem;
overflow: hidden;
}
.tag-resolved {
color: #22c55e;
border-color: rgba(34, 197, 94, 0.3);
}
.thread {
position: relative;
max-width: 100%;
overflow-wrap: break-word;
word-wrap: break-word;
p {
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
}
h3 {
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
}
}
.thread :global(mark) {
background-color: hsl(var(--web-color-pink-500) / 0.5);
}
h3 {
margin-block-end: 0.25rem;
}
.web-tag {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>