summaryrefslogtreecommitdiff
path: root/src/components/BackendList.tsx
blob: bb9ae530019d6bad3d33b9b9a15898c5cf4e909e (plain)
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
120
import cx from 'clsx';
import * as React from 'react';
import { Eye, EyeOff, X as Close } from '~/components/shared/FeatherIcons';

import { useToggle } from '~/hooks/basic';
import type { ClashAPIConfigWithAddedAt } from '~/store/types';
import type { ClashAPIConfig } from '~/types';

import s from './BackendList.module.scss';

type Props = {
  apiConfigs: ClashAPIConfigWithAddedAt[];
  selectedClashAPIConfigIndex: number;
  onRemove: (x: ClashAPIConfig) => void;
  onSelect: (x: ClashAPIConfig) => void;
};

export function BackendList({
  apiConfigs,
  selectedClashAPIConfigIndex,
  onRemove,
  onSelect,
}: Props) {
  return (
    <>
      <ul className={s.ul}>
        {apiConfigs.map((item, idx) => {
          return (
            <li
              className={cx(s.li, {
                [s.hasSecret]: item.secret,
                [s.isSelected]: idx === selectedClashAPIConfigIndex,
              })}
              key={item.baseURL + item.secret}
            >
              <Item
                disableRemove={idx === selectedClashAPIConfigIndex}
                baseURL={item.baseURL}
                secret={item.secret}
                onRemove={onRemove}
                onSelect={onSelect}
              />
            </li>
          );
        })}
      </ul>
    </>
  );
}

function Item({
  baseURL,
  secret,
  disableRemove,
  onRemove,
  onSelect,
}: {
  baseURL: string;
  secret?: string;
  disableRemove: boolean;
  onRemove: (x: ClashAPIConfig) => void;
  onSelect: (x: ClashAPIConfig) => void;
}) {
  const [show, toggle] = useToggle();
  const Icon = show ? EyeOff : Eye;

  const handleTap = React.useCallback((e: React.KeyboardEvent) => {
    e.stopPropagation();
  }, []);

  return (
    <>
      <Button
        disabled={disableRemove}
        onClick={() => onRemove({ baseURL, secret })}
        className={s.close}
      >
        <Close size={20} />
      </Button>
      <span
        className={s.url}
        tabIndex={0}
        role="button"
        onClick={() => onSelect({ baseURL, secret })}
        onKeyUp={handleTap}
      >
        {baseURL}
      </span>
      <span />
      {secret ? (
        <>
          <span className={s.secret}>{show ? secret : '***'}</span>

          <Button onClick={toggle} className={s.eye}>
            <Icon size={20} />
          </Button>
        </>
      ) : null}
    </>
  );
}

function Button({
  children,
  onClick,
  className,
  disabled,
}: {
  children: React.ReactNode;

  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => unknown;
  className: string;
  disabled?: boolean;
}) {
  return (
    <button disabled={disabled} className={cx(className, s.btn)} onClick={onClick}>
      {children}
    </button>
  );
}