parent
ff0cf2f9dc
commit
5c70456e18
@ -0,0 +1,14 @@
|
|||||||
|
@import "./window.scss";
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
|
import EmojiPicker, { Emoji, Theme as EmojiTheme } from "emoji-picker-react";
|
||||||
|
|
||||||
|
import styles from "./settings.module.scss";
|
||||||
|
|
||||||
|
import ResetIcon from "../icons/reload.svg";
|
||||||
|
|
||||||
|
import { List, ListItem, Popover } from "./ui-lib";
|
||||||
|
|
||||||
|
import { IconButton } from "./button";
|
||||||
|
import { SubmitKey, useChatStore, Theme } from "../store";
|
||||||
|
import { Avatar } from "./home";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
|
export function Settings() {
|
||||||
|
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
||||||
|
const [config, updateConfig, resetConfig] = useChatStore((state) => [
|
||||||
|
state.config,
|
||||||
|
state.updateConfig,
|
||||||
|
state.resetConfig,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles["window-header"]}>
|
||||||
|
<div>
|
||||||
|
<div className={styles["window-header-title"]}>设置</div>
|
||||||
|
<div className={styles["window-header-sub-title"]}>设置选项</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles["window-actions"]}>
|
||||||
|
<div className={styles["window-action-button"]}>
|
||||||
|
<IconButton
|
||||||
|
icon={<ResetIcon />}
|
||||||
|
onClick={resetConfig}
|
||||||
|
bordered
|
||||||
|
title="重置所有选项"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles["settings"]}>
|
||||||
|
<List>
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>头像</div>
|
||||||
|
<Popover
|
||||||
|
onClose={() => setShowEmojiPicker(false)}
|
||||||
|
content={
|
||||||
|
<EmojiPicker
|
||||||
|
lazyLoadEmojis
|
||||||
|
theme={EmojiTheme.AUTO}
|
||||||
|
onEmojiClick={(e) => {
|
||||||
|
updateConfig((config) => (config.avatar = e.unified));
|
||||||
|
setShowEmojiPicker(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
open={showEmojiPicker}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={styles.avatar}
|
||||||
|
onClick={() => setShowEmojiPicker(true)}
|
||||||
|
>
|
||||||
|
<Avatar role="user" />
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>发送键</div>
|
||||||
|
<div className="">
|
||||||
|
<select
|
||||||
|
value={config.submitKey}
|
||||||
|
onChange={(e) => {
|
||||||
|
updateConfig(
|
||||||
|
(config) =>
|
||||||
|
(config.submitKey = e.target.value as any as SubmitKey)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Object.values(SubmitKey).map((v) => (
|
||||||
|
<option value={v} key={v}>
|
||||||
|
{v}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>主题</div>
|
||||||
|
<div className="">
|
||||||
|
<select
|
||||||
|
value={config.theme}
|
||||||
|
onChange={(e) => {
|
||||||
|
updateConfig(
|
||||||
|
(config) => (config.theme = e.target.value as any as Theme)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Object.values(Theme).map((v) => (
|
||||||
|
<option value={v} key={v}>
|
||||||
|
{v}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>紧凑边框</div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.tightBorder}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateConfig(
|
||||||
|
(config) => (config.tightBorder = e.currentTarget.checked)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
></input>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
<List>
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>最大上下文消息数</div>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
title={config.historyMessageCount.toString()}
|
||||||
|
value={config.historyMessageCount}
|
||||||
|
min="5"
|
||||||
|
max="20"
|
||||||
|
step="5"
|
||||||
|
onChange={(e) =>
|
||||||
|
updateConfig(
|
||||||
|
(config) =>
|
||||||
|
(config.historyMessageCount = e.target.valueAsNumber)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
></input>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem>
|
||||||
|
<div className={styles["settings-title"]}>
|
||||||
|
上下文中包含机器人消息
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.sendBotMessages}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateConfig(
|
||||||
|
(config) => (config.sendBotMessages = e.currentTarget.checked)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
></input>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
.window-header {
|
||||||
|
padding: 14px 20px;
|
||||||
|
border-bottom: rgba(0, 0, 0, 0.1) 1px solid;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-header-title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bolder;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-header-sub-title {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-actions {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-action-button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
@ -0,0 +1,228 @@
|
|||||||
|
# proxychains.conf FOR PROXYCHAINS.EXE ALPHA
|
||||||
|
#
|
||||||
|
# SOCKS5 tunneling proxifier with Fake DNS.
|
||||||
|
#
|
||||||
|
|
||||||
|
# The option below identifies how the ProxyList is treated.
|
||||||
|
# only one option should be uncommented at time,
|
||||||
|
# otherwise the last appearing option will be accepted
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DYNAMIC_CHAIN IS NOT SUPPORTED AT PRESENT
|
||||||
|
#dynamic_chain
|
||||||
|
# DYNAMIC_CHAIN IS NOT SUPPORTED AT PRESENT
|
||||||
|
#
|
||||||
|
# Dynamic - Each connection will be done via chained proxies
|
||||||
|
# all proxies chained in the order as they appear in the list
|
||||||
|
# at least one proxy must be online to play in chain
|
||||||
|
# (dead proxies are skipped)
|
||||||
|
# otherwise EINTR is returned to the app
|
||||||
|
#
|
||||||
|
#
|
||||||
|
strict_chain
|
||||||
|
#
|
||||||
|
# Strict - Each connection will be done via chained proxies
|
||||||
|
# all proxies chained in the order as they appear in the list
|
||||||
|
# all proxies must be online to play in chain
|
||||||
|
# otherwise EINTR is returned to the app
|
||||||
|
#
|
||||||
|
# RANDOM_CHAIN IS NOT SUPPORTED AT PRESENT
|
||||||
|
#random_chain
|
||||||
|
# RANDOM_CHAIN IS NOT SUPPORTED AT PRESENT
|
||||||
|
#
|
||||||
|
# Random - Each connection will be done via random proxy
|
||||||
|
# (or proxy chain, see chain_len) from the list.
|
||||||
|
# this option is good to test your IDS :)
|
||||||
|
|
||||||
|
# Make sense only if random_chain
|
||||||
|
#chain_len = 2
|
||||||
|
|
||||||
|
# Quiet mode (no output from library)
|
||||||
|
#quiet_mode
|
||||||
|
|
||||||
|
# Proxy DNS requests using Fake IP - no leak for DNS data
|
||||||
|
proxy_dns
|
||||||
|
|
||||||
|
# Proxy DNS requests using UDP associate feature provided by SOCKS5 proxy
|
||||||
|
# NOT SUPPORTED AT PRESENT
|
||||||
|
#proxy_dns_udp_associate
|
||||||
|
# NOT SUPPORTED AT PRESENT
|
||||||
|
|
||||||
|
# set the class A subnet number to usefor use of the internal remote DNS mapping
|
||||||
|
# we use the reserved 224.x.x.x range by default,
|
||||||
|
# if the proxified app does a DNS request, we will return an IP from that range.
|
||||||
|
# on further accesses to this ip we will send the saved DNS name to the proxy.
|
||||||
|
# in case some control-freak app checks the returned ip, and denies to
|
||||||
|
# connect, you can use another subnet, e.g. 10.x.x.x or 127.x.x.x.
|
||||||
|
# of course you should make sure that the proxified app does not need
|
||||||
|
# *real* access to this subnet.
|
||||||
|
# i.e. dont use the same subnet then in the localnet section
|
||||||
|
#remote_dns_subnet 127
|
||||||
|
#remote_dns_subnet 10
|
||||||
|
remote_dns_subnet 224
|
||||||
|
|
||||||
|
# This enables you to set a CIDR block for the internal remote DNS mapping
|
||||||
|
# for example, remote_dns_subnet_cidr_v4 224.0.0.0/8 is equivalent to
|
||||||
|
# remote_dns_subnet 224.
|
||||||
|
# subnet mask format like 255.255.0.0 is not allowed here
|
||||||
|
# By default 224.0.0.0/8 and 250d::/16
|
||||||
|
#remote_dns_subnet_cidr_v4 224.0.0.0/8
|
||||||
|
#remote_dns_subnet_cidr_v6 250d::/16
|
||||||
|
|
||||||
|
# Some timeouts in milliseconds
|
||||||
|
# Defaults: tcp_read_time_out 5000, tcp_connect_time_out 3000
|
||||||
|
#tcp_read_time_out 15000
|
||||||
|
#tcp_connect_time_out 8000
|
||||||
|
|
||||||
|
|
||||||
|
# ==== Rules ====
|
||||||
|
# You can control which IP range not to be proxied.
|
||||||
|
# First matched rule decides the target (PROXIED, DIRECT or BLOCK) of a
|
||||||
|
# connection.
|
||||||
|
|
||||||
|
# localnet always has a "DIRECT" target, which means they will not be
|
||||||
|
# proxied.
|
||||||
|
# By default enable localnet for loopback address ranges
|
||||||
|
# RFC5735 Loopback address range
|
||||||
|
localnet 127.0.0.0/255.0.0.0
|
||||||
|
# RFC1918 Private Address Ranges
|
||||||
|
# localnet 10.0.0.0/255.0.0.0
|
||||||
|
# localnet 172.16.0.0/255.240.0.0
|
||||||
|
# localnet 192.168.0.0/255.255.0.0
|
||||||
|
|
||||||
|
|
||||||
|
# Example for localnet exclusion
|
||||||
|
## Exclude connections to 192.168.1.0/24 with port 80
|
||||||
|
# localnet 192.168.1.0:80/255.255.255.0
|
||||||
|
|
||||||
|
## Exclude connections to 192.168.100.0/24
|
||||||
|
# localnet 192.168.100.0/255.255.255.0
|
||||||
|
|
||||||
|
## Exclude connections to ANYwhere with port 80
|
||||||
|
# localnet 0.0.0.0:80/0.0.0.0
|
||||||
|
|
||||||
|
# === Additional routing rules ===
|
||||||
|
# These rules enables further control on websites/addresses which
|
||||||
|
# should be proxied or not.
|
||||||
|
# All rules can have an extra optional restriction of target port.
|
||||||
|
# However, if the proxied application uses gethostbyname() to do DNS
|
||||||
|
# query instead of getaddrinfo() series, this port part of the rule
|
||||||
|
# is invalidated.
|
||||||
|
# Three target is allowed: PROXY, DIRECT and BLOCK.
|
||||||
|
#
|
||||||
|
# - DOMAIN-KEYWORD rule, matching requests where the FQDN contains
|
||||||
|
# a specific string.
|
||||||
|
# e.g. DOMAIN-KEYWORD,google:80,DIRECT means any request to FQDN
|
||||||
|
# containing "google" with the target port 80 will NOT be proxied.
|
||||||
|
#
|
||||||
|
# - DOMAIN-SUFFIX rule, matching requests where the FQDN is suffixed
|
||||||
|
# with a specific string.
|
||||||
|
# e.g. DOMAIN-SUFFIX,.ru,PROXY means any FQDN that ends with ".ru"
|
||||||
|
# will be proxied.
|
||||||
|
#
|
||||||
|
# - DOMAIN-FULL rule, matching requests where the FQDN is exactly
|
||||||
|
# identical to a specific string.
|
||||||
|
# e.g. DOMAIN-FULL,duckduckgo.com,DIRECT means every request to
|
||||||
|
# "duckduckgo.com" (must entirely match) will NOT be proxied.
|
||||||
|
#
|
||||||
|
# - DOMAIN rule, the alias of DOMAIN-FULL rule.
|
||||||
|
#
|
||||||
|
# - IP-CIDR rule, matching requests to IP address in a CIDR block.
|
||||||
|
# Note if an FQDN is previously matched by a DOMAIN* rule, this rule
|
||||||
|
# is not applied to the resolved IPs. (Because fake IPs are used in
|
||||||
|
# this case)
|
||||||
|
# e.g. IP-CIDR,8.8.8.8/32,DIRECT
|
||||||
|
# IP-CIDR,250e::/16,PROXY
|
||||||
|
# IP-CIDR,[250c::]:443/16,PROXY
|
||||||
|
# IP-CIDR,10.0.0.0:80/8,DIRECT
|
||||||
|
# Note that "IP-CIDR,127.0.0.0/8,DIRECT" is equivalent to
|
||||||
|
# "localnet 127.0.0.0/255.0.0.0".
|
||||||
|
IP-CIDR,10.0.0.0/8,DIRECT
|
||||||
|
IP-CIDR,172.16.0.0/12,DIRECT
|
||||||
|
IP-CIDR,192.168.0.0/255.255.0.0,DIRECT
|
||||||
|
IP-CIDR,fe80::/8,DIRECT
|
||||||
|
# - PORT rule, matching requests to a target port.
|
||||||
|
# e.g. PORT,25,BLOCK
|
||||||
|
#
|
||||||
|
# - FINAL "rule", deciding the destiny of a request immediately.
|
||||||
|
# When this "rule" is used, it is not treated as a "match".
|
||||||
|
# If you want an unconditional match, try other rules instead, like
|
||||||
|
# IP-CIDR,0.0.0.0/0,PROXY or DOMAIN-KEYWORD,,PROXY.
|
||||||
|
#
|
||||||
|
# When no rules and no FINAL "rule" matched, a connection will be
|
||||||
|
# PROXIED by default, unless you specify option default_target.
|
||||||
|
# e.g. FINAL,PROXY
|
||||||
|
|
||||||
|
# Will fake IP entries created by a descendant process be removed if this
|
||||||
|
# process exited? 1 by default.
|
||||||
|
delete_fake_ip_after_child_exits 1
|
||||||
|
|
||||||
|
# When no rules and no FINAL "rule" matched, a connection's default
|
||||||
|
# target. PROXY by default.
|
||||||
|
default_target PROXY
|
||||||
|
|
||||||
|
# Will the rules apply to the resolved IP if corresponding hostname
|
||||||
|
# did not match any rules? (FINAL is not counted as a rule)
|
||||||
|
# IF SO, SET THIS OPTION'S VALUE TO 0. 1 by default.
|
||||||
|
use_fake_ip_when_hostname_not_matched 1
|
||||||
|
|
||||||
|
# ===== Keep them as-is =====
|
||||||
|
|
||||||
|
map_resolved_ip_to_host 0
|
||||||
|
search_for_host_by_resolved_ip 0
|
||||||
|
# or force_resolve_by_hosts_file 1
|
||||||
|
resolve_locally_if_match_hosts 1
|
||||||
|
|
||||||
|
# ===== Keep them as-is - end =====
|
||||||
|
|
||||||
|
# Generate fake ips by FQDN hash - 1 (better to get rid of SSH safe
|
||||||
|
# warnings)
|
||||||
|
# Generate fake ips sequentially - 0
|
||||||
|
# Default: 1
|
||||||
|
gen_fake_ip_using_hashed_hostname 1
|
||||||
|
|
||||||
|
# If your *first* proxy supports connecting to it by an IPv4 address
|
||||||
|
# (resolved by a hostname or specified manually), set its value to 1.
|
||||||
|
# This enables proxying IPv4 address.
|
||||||
|
# If disabled, fake IPv4 address is not returned.
|
||||||
|
# 1 by default
|
||||||
|
first_tunnel_uses_ipv4 1
|
||||||
|
|
||||||
|
# If your *first* proxy supports connecting to it by an IPv6 address
|
||||||
|
# (resolved by a hostname or specified manually), set its value to 1.
|
||||||
|
# This enables proxying IPv6 address.
|
||||||
|
# If disabled, fake IPv6 address is not returned.
|
||||||
|
# 0 by default
|
||||||
|
first_tunnel_uses_ipv6 0
|
||||||
|
|
||||||
|
# Custom hosts file path
|
||||||
|
#custom_hosts_file_path C:\Some Path\hosts
|
||||||
|
#custom_hosts_file_path /etc/alternative/hosts
|
||||||
|
|
||||||
|
# Custom log level.
|
||||||
|
# 600 - VERBOSE
|
||||||
|
# 500 - DEBUG
|
||||||
|
# 400 - INFO
|
||||||
|
# 300 - WARNING
|
||||||
|
# 200 - ERROR
|
||||||
|
# 100 - CRITICAL
|
||||||
|
# "log_level 200" is equivalent to "quiet_mode"
|
||||||
|
log_level 400
|
||||||
|
|
||||||
|
# ProxyList format
|
||||||
|
# type host port [user pass]
|
||||||
|
# (values separated by 'tab' or 'blank')
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# socks5 localhost 1080
|
||||||
|
# socks5 localhost 1080 user password
|
||||||
|
# socks5 192.168.67.78 1080 lamer secret
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# proxy types: socks5
|
||||||
|
# ( auth types supported: "user/pass"-socks5 )
|
||||||
|
#
|
||||||
|
[ProxyList]
|
||||||
|
socks5 localhost 7890
|
Loading…
Reference in new issue