File size: 3,018 Bytes
3199d61
 
 
 
 
064bfd6
3199d61
 
 
 
064bfd6
3199d61
 
 
 
 
 
 
064bfd6
3199d61
 
 
 
064bfd6
3199d61
 
 
 
064bfd6
3199d61
064bfd6
3199d61
064bfd6
3199d61
 
 
 
 
 
064bfd6
3199d61
 
 
 
 
064bfd6
 
3199d61
064bfd6
3199d61
064bfd6
3199d61
 
064bfd6
3199d61
 
 
 
 
 
 
 
 
 
 
 
d8a167e
3199d61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
064bfd6
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
import * as React from 'react'
import { stringWidth } from '../../ink/stringWidth.js'
import { Box, Text } from '../../ink.js'
import { truncate } from '../../utils/format.js'

export type FeedLine = {
  text: string
  timestamp?: string
}

export type FeedConfig = {
  title: string
  lines: FeedLine[]
  footer?: string
  emptyMessage?: string
  customContent?: { content: React.ReactNode; width: number }
}

type FeedProps = {
  config: FeedConfig
  actualWidth: number
}

export function calculateFeedWidth(config: FeedConfig): number {
  const { title, lines, footer, emptyMessage, customContent } = config

  let maxWidth = stringWidth(title)

  if (customContent !== undefined) {
    maxWidth = Math.max(maxWidth, customContent.width)
  } else if (lines.length === 0 && emptyMessage) {
    maxWidth = Math.max(maxWidth, stringWidth(emptyMessage))
  } else {
    const gap = '  '
    const maxTimestampWidth = Math.max(
      0,
      ...lines.map(line => (line.timestamp ? stringWidth(line.timestamp) : 0)),
    )

    for (const line of lines) {
      const timestampWidth = maxTimestampWidth > 0 ? maxTimestampWidth : 0
      const lineWidth =
        stringWidth(line.text) +
        (timestampWidth > 0 ? timestampWidth + gap.length : 0)
      maxWidth = Math.max(maxWidth, lineWidth)
    }
  }

  if (footer) {
    maxWidth = Math.max(maxWidth, stringWidth(footer))
  }

  return maxWidth
}

export function Feed({ config, actualWidth }: FeedProps): React.ReactNode {
  const { title, lines, footer, emptyMessage, customContent } = config

  const gap = '  '
  const maxTimestampWidth = Math.max(
    0,
    ...lines.map(line => (line.timestamp ? stringWidth(line.timestamp) : 0)),
  )

  return (
    <Box flexDirection="column" width={actualWidth}>
      <Text bold color="clawd_body">
        {title}
      </Text>
      {customContent ? (
        <>
          {customContent.content}
          {footer && (
            <Text dimColor italic>
              {truncate(footer, actualWidth)}
            </Text>
          )}
        </>
      ) : lines.length === 0 && emptyMessage ? (
        <Text dimColor>{truncate(emptyMessage, actualWidth)}</Text>
      ) : (
        <>
          {lines.map((line, index) => {
            const textWidth = Math.max(
              10,
              actualWidth -
                (maxTimestampWidth > 0 ? maxTimestampWidth + gap.length : 0),
            )

            return (
              <Text key={index}>
                {maxTimestampWidth > 0 && (
                  <>
                    <Text dimColor>
                      {(line.timestamp || '').padEnd(maxTimestampWidth)}
                    </Text>
                    {gap}
                  </>
                )}
                <Text>{truncate(line.text, textWidth)}</Text>
              </Text>
            )
          })}
          {footer && (
            <Text dimColor italic>
              {truncate(footer, actualWidth)}
            </Text>
          )}
        </>
      )}
    </Box>
  )
}