chore: 通過 ESM 引入外部脚本
* React, ReactDOM 和 CryptoES * 集中在 Imports.ts 中 * 向每一個 JSX 添加 React 的 import
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
|
import { CryptoES } from './Imports.ts'
|
||||||
|
|
||||||
const dataIsEmpty = !localStorage.tws_data || localStorage.tws_data == ''
|
const dataIsEmpty = !localStorage.tws_data || localStorage.tws_data == ''
|
||||||
|
|
||||||
const aes = {
|
const aes = {
|
||||||
enc: (m: string, k: string) => CryptoJS.AES.encrypt(m, k).toString(),
|
enc: (m: string, k: string) => CryptoES.AES.encrypt(m, k).toString(CryptoES.enc.Utf8),
|
||||||
dec: (m: string, k: string) => CryptoJS.AES.decrypt(m, k).toString(CryptoJS.enc.Utf8),
|
dec: (m: string, k: string) => CryptoES.AES.decrypt(m, k).toString(CryptoES.enc.Utf8),
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = location.host + '_TWS_姐姐'
|
const key = location.host + '_TWS_姐姐'
|
||||||
|
|||||||
9
client/Imports.ts
Normal file
9
client/Imports.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import * as React from 'https://esm.sh/react@18.3.1'
|
||||||
|
import * as ReactDOM from 'https://esm.sh/react-dom@18.3.1'
|
||||||
|
import CryptoES from 'https://unpkg.com/crypto-es@3.0.4/dist/index.mjs'
|
||||||
|
|
||||||
|
export {
|
||||||
|
React,
|
||||||
|
ReactDOM,
|
||||||
|
CryptoES,
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import Client from "../api/Client.ts";
|
import Client from "../api/Client.ts"
|
||||||
import data from "../Data.ts";
|
import data from "../Data.ts"
|
||||||
import ChatFragment from "./chat/ChatFragment.jsx"
|
import ChatFragment from "./chat/ChatFragment.jsx"
|
||||||
import LoginDialog from "./dialog/LoginDialog.jsx"
|
import LoginDialog from "./dialog/LoginDialog.jsx"
|
||||||
import ContactsListItem from "./main/ContactsListItem.jsx"
|
import ContactsListItem from "./main/ContactsListItem.jsx"
|
||||||
import RecentsListItem from "./main/RecentsListItem.jsx"
|
import RecentsListItem from "./main/RecentsListItem.jsx"
|
||||||
import snackbar from "./snackbar.js";
|
import snackbar from "./snackbar.js"
|
||||||
import useEventListener from './useEventListener.js'
|
import useEventListener from './useEventListener.js'
|
||||||
|
|
||||||
|
import { React } from '../Imports.ts'
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [recentsList, setRecentsList] = React.useState([
|
const [recentsList, setRecentsList] = React.useState([
|
||||||
/* {
|
/* {
|
||||||
@@ -51,16 +53,19 @@ export default function App() {
|
|||||||
loginButtonRef
|
loginButtonRef
|
||||||
] = [React.useRef(null), React.useRef(null), React.useRef(null), React.useRef(null), React.useRef(null)]
|
] = [React.useRef(null), React.useRef(null), React.useRef(null), React.useRef(null), React.useRef(null)]
|
||||||
|
|
||||||
React.useEffect(async () => {
|
React.useEffect(() => {
|
||||||
Client.connect()
|
; (async () => {
|
||||||
const re = await Client.invoke("User.auth", {
|
Client.connect()
|
||||||
access_token: data.access_token,
|
const re = await Client.invoke("User.auth", {
|
||||||
})
|
access_token: data.access_token,
|
||||||
if (re.code == 401)
|
})
|
||||||
loginDialogRef.current.show()
|
if (re.code == 401)
|
||||||
else if (re.code != 200)
|
loginDialogRef.current.show()
|
||||||
snackbar("驗證失敗: " + re.msg)
|
else if (re.code != 200)
|
||||||
})
|
snackbar("驗證失敗: " + re.msg)
|
||||||
|
})()
|
||||||
|
return () => { }
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
@@ -70,7 +75,7 @@ export default function App() {
|
|||||||
height: 'var(--whitesilk-window-height)',
|
height: 'var(--whitesilk-window-height)',
|
||||||
}}>
|
}}>
|
||||||
<LoginDialog
|
<LoginDialog
|
||||||
ref={loginDialogRef}
|
loginDialogRef={loginDialogRef}
|
||||||
inputAccountRef={inputAccountRef}
|
inputAccountRef={inputAccountRef}
|
||||||
inputPasswordRef={inputPasswordRef}
|
inputPasswordRef={inputPasswordRef}
|
||||||
registerButtonRef={registerButtonRef}
|
registerButtonRef={registerButtonRef}
|
||||||
@@ -91,66 +96,68 @@ export default function App() {
|
|||||||
{
|
{
|
||||||
// 侧边列表
|
// 侧边列表
|
||||||
}
|
}
|
||||||
{
|
<div id="SideBar">
|
||||||
// 最近聊天
|
{
|
||||||
<mdui-list style={{
|
// 最近聊天
|
||||||
width: "35%",
|
<mdui-list style={{
|
||||||
overflowY: 'auto',
|
width: "35%",
|
||||||
paddingRight: '10px',
|
overflowY: 'auto',
|
||||||
display: navigationItemSelected == "Recents" ? null : 'none'
|
paddingRight: '10px',
|
||||||
}}>
|
display: navigationItemSelected == "Recents" ? null : 'none'
|
||||||
{
|
}}>
|
||||||
recentsList.map((v) =>
|
|
||||||
<RecentsListItem
|
|
||||||
key={v.userId}
|
|
||||||
nickName={v.nickName}
|
|
||||||
avatar={v.avatar}
|
|
||||||
content={v.content} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</mdui-list>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// 联系人列表
|
|
||||||
<mdui-list style={{
|
|
||||||
width: "35%",
|
|
||||||
overflowY: 'auto',
|
|
||||||
paddingRight: '10px',
|
|
||||||
display: navigationItemSelected == "Contacts" ? null : 'none'
|
|
||||||
}}>
|
|
||||||
<mdui-collapse accordion value={Object.keys(contactsMap)[0]}>
|
|
||||||
{
|
{
|
||||||
Object.keys(contactsMap).map((v) =>
|
recentsList.map((v) =>
|
||||||
<mdui-collapse-item key={v} value={v}>
|
<RecentsListItem
|
||||||
<mdui-list-subheader slot="header">{v}</mdui-list-subheader>
|
key={v.userId}
|
||||||
{
|
nickName={v.nickName}
|
||||||
contactsMap[v].map((v2) =>
|
avatar={v.avatar}
|
||||||
<ContactsListItem
|
content={v.content} />
|
||||||
key={v2.userId}
|
|
||||||
nickName={v2.nickName}
|
|
||||||
avatar={v2.avatar} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</mdui-collapse-item>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</mdui-collapse>
|
</mdui-list>
|
||||||
</mdui-list>
|
}
|
||||||
}
|
{
|
||||||
|
// 联系人列表
|
||||||
|
<mdui-list style={{
|
||||||
|
width: "35%",
|
||||||
|
overflowY: 'auto',
|
||||||
|
paddingRight: '10px',
|
||||||
|
display: navigationItemSelected == "Contacts" ? null : 'none'
|
||||||
|
}}>
|
||||||
|
<mdui-collapse accordion value={Object.keys(contactsMap)[0]}>
|
||||||
|
{
|
||||||
|
Object.keys(contactsMap).map((v) =>
|
||||||
|
<mdui-collapse-item key={v} value={v}>
|
||||||
|
<mdui-list-subheader slot="header">{v}</mdui-list-subheader>
|
||||||
|
{
|
||||||
|
contactsMap[v].map((v2) =>
|
||||||
|
<ContactsListItem
|
||||||
|
key={v2.userId}
|
||||||
|
nickName={v2.nickName}
|
||||||
|
avatar={v2.avatar} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</mdui-collapse-item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</mdui-collapse>
|
||||||
|
</mdui-list>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
// 分割线
|
// 分割线
|
||||||
}
|
}
|
||||||
<div style={{
|
{/* <div style={{
|
||||||
// 我们删除了 body 的padding 因此不需要再 calc 了
|
// 我们删除了 body 的padding 因此不需要再 calc 了
|
||||||
height: 'var(--whitesilk-window-height)',
|
height: 'var(--whitesilk-window-height)',
|
||||||
marginRight: '10px',
|
marginRight: '10px',
|
||||||
}}>
|
}}>
|
||||||
<mdui-divider vertical></mdui-divider>
|
<mdui-divider vertical></mdui-divider>
|
||||||
</div>
|
</div> */}
|
||||||
{
|
{
|
||||||
// 聊天页面
|
// 聊天页面
|
||||||
}
|
}
|
||||||
<ChatFragment />
|
<ChatFragment id="ChatFragment" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { React } from '../Imports.ts'
|
||||||
|
|
||||||
export default function Avatar({ src, text, icon = 'person', ...props } = {}) {
|
export default function Avatar({ src, text, icon = 'person', ...props } = {}) {
|
||||||
return (
|
return (
|
||||||
src ? <mdui-avatar {...props}>
|
src ? <mdui-avatar {...props}>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import Message from "./Message.jsx"
|
import Message from "./Message.jsx"
|
||||||
import MessageContainer from "./MessageContainer.jsx"
|
import MessageContainer from "./MessageContainer.jsx"
|
||||||
|
|
||||||
export default function ChatFragment() {
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
|
export default function ChatFragment({ ...props } = {}) {
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@@ -9,7 +11,7 @@ export default function ChatFragment() {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
}}>
|
}} {...props}>
|
||||||
<mdui-top-app-bar style={{
|
<mdui-top-app-bar style={{
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
}}>
|
}}>
|
||||||
@@ -48,7 +50,7 @@ export default function ChatFragment() {
|
|||||||
bottom: '0',
|
bottom: '0',
|
||||||
backgroundColor: 'rgb(var(--mdui-color-background))',
|
backgroundColor: 'rgb(var(--mdui-color-background))',
|
||||||
}}>
|
}}>
|
||||||
<mdui-text-field variant="outlined" placeholder="喵呜~" style={{
|
<mdui-text-field variant="outlined" placeholder="喵呜~" autosize max-rows="1" style={{
|
||||||
marginRight: '10px',
|
marginRight: '10px',
|
||||||
}}></mdui-text-field>
|
}}></mdui-text-field>
|
||||||
<mdui-button-icon slot="end-icon" icon="more_vert" style={{
|
<mdui-button-icon slot="end-icon" icon="more_vert" style={{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import Avatar from "../Avatar.jsx"
|
import Avatar from "../Avatar.jsx"
|
||||||
|
|
||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一条消息
|
* 一条消息
|
||||||
* @param { Object } param
|
* @param { Object } param
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息容器
|
* 消息容器
|
||||||
* @returns { React.JSX.Element }
|
* @returns { React.JSX.Element }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一条系统提示消息
|
* 一条系统提示消息
|
||||||
* @returns { React.JSX.Element }
|
* @returns { React.JSX.Element }
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
export default function LoginDialog({
|
export default function LoginDialog({
|
||||||
inputAccountRef,
|
inputAccountRef,
|
||||||
inputPasswordRef,
|
inputPasswordRef,
|
||||||
registerButtonRef,
|
registerButtonRef,
|
||||||
loginButtonRef,
|
loginButtonRef,
|
||||||
...prop
|
loginDialogRef
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<mdui-dialog headline="登录" {...prop}>
|
<mdui-dialog headline="登录" ref={loginDialogRef}>
|
||||||
|
|
||||||
<mdui-text-field label="账号" ref={inputAccountRef}></mdui-text-field>
|
<mdui-text-field label="账号" ref={inputAccountRef}></mdui-text-field>
|
||||||
<div style={{
|
<div style={{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import Avatar from "../Avatar.jsx"
|
import Avatar from "../Avatar.jsx"
|
||||||
|
|
||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
export default function ContactsListItem({ nickName, avatar }) {
|
export default function ContactsListItem({ nickName, avatar }) {
|
||||||
return (
|
return (
|
||||||
<mdui-list-item rounded style={{
|
<mdui-list-item rounded style={{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import Avatar from "../Avatar.jsx"
|
import Avatar from "../Avatar.jsx"
|
||||||
|
|
||||||
|
import { React } from '../../Imports.ts'
|
||||||
|
|
||||||
export default function RecentsListItem({ nickName, avatar, content }) {
|
export default function RecentsListItem({ nickName, avatar, content }) {
|
||||||
return (
|
return (
|
||||||
<mdui-list-item rounded style={{
|
<mdui-list-item rounded style={{
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export default function snackbar(text) {
|
export default function snackbar(text) {
|
||||||
$("#public_snackbar").text(text).get(0).open()
|
$("#public_snackbar").text(text).get(0).open()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
* @param { Event } event
|
* @param { Event } event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { React } from "../Imports.ts"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定事件
|
* 绑定事件
|
||||||
* @param { React.Ref } ref
|
* @param { React.Ref } ref
|
||||||
|
|||||||
Reference in New Issue
Block a user