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