Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
c53d5c21
Commit
c53d5c21
authored
Aug 09, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
optimize: init
parent
21b2db98
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
135 additions
and
52 deletions
+135
-52
src/infra/eventbus.ts
src/infra/eventbus.ts
+2
-2
src/infra/index.ts
src/infra/index.ts
+2
-2
src/infra/pfetch.ts
src/infra/pfetch.ts
+35
-0
src/middleware/sqlite.ts
src/middleware/sqlite.ts
+5
-1
src/stores/initStore.ts
src/stores/initStore.ts
+1
-0
src/ui/Layout/index.module.scss
src/ui/Layout/index.module.scss
+11
-1
src/ui/Layout/index.tsx
src/ui/Layout/index.tsx
+19
-18
src/ui/Layout/utils.ts
src/ui/Layout/utils.ts
+58
-9
src/ui/Match/index.tsx
src/ui/Match/index.tsx
+2
-19
No files found.
src/infra/eventbus.ts
View file @
c53d5c21
import
{
EventEmitter
}
from
"
eventemitter3
"
;
import
{
EventEmitter
}
from
"
eventemitter3
"
;
import
{
v4
as
v4uuid
}
from
"
uuid
"
;
import
{
v4
as
v4uuid
}
from
"
uuid
"
;
export
const
eventEmitter
=
new
EventEmitter
();
const
eventEmitter
=
new
EventEmitter
();
export
enum
Task
{
export
enum
Task
{
Move
=
"
move
"
,
// 卡片移动
Move
=
"
move
"
,
// 卡片移动
...
@@ -13,7 +13,7 @@ export enum Task {
...
@@ -13,7 +13,7 @@ export enum Task {
const
getEnd
=
(
task
:
Task
)
=>
`
${
task
}
-end`
;
const
getEnd
=
(
task
:
Task
)
=>
`
${
task
}
-end`
;
/** 在组件之中注册方法 */
/** 在组件之中注册方法
,注意注册的方法一旦执行成功,必须返回一个true
*/
const
register
=
<
T
extends
unknown
[]
>
(
const
register
=
<
T
extends
unknown
[]
>
(
task
:
Task
,
task
:
Task
,
fn
:
(...
args
:
T
)
=>
Promise
<
boolean
>
fn
:
(...
args
:
T
)
=>
Promise
<
boolean
>
...
...
src/infra/index.ts
View file @
c53d5c21
// Some implementation of infrastructure
// Some implementation of infrastructure
/* eslint import/export: 0 */
import
"
./console
"
;
export
*
from
"
./console
"
;
export
*
from
"
./eventbus
"
;
export
*
from
"
./eventbus
"
;
export
*
from
"
./pfetch
"
;
export
*
from
"
./sleep
"
;
export
*
from
"
./sleep
"
;
export
*
from
"
./stream
"
;
export
*
from
"
./stream
"
;
src/infra/pfetch.ts
0 → 100644
View file @
c53d5c21
/** 在fetch的基础上,封装一个pfetch。增加一个可选的新参数,这个参数是一个回调函数,从而让外界可以感知fetch的进度(0->1),比如下载进度。 */
export
async
function
pfetch
(
input
:
RequestInfo
,
options
?:
{
init
?:
RequestInit
;
progressCallback
?:
(
progress
:
number
)
=>
void
;
}
):
Promise
<
Response
>
{
const
response
=
await
fetch
(
input
,
options
?.
init
);
const
clonedResponse
=
response
.
clone
();
// Clone the response to create a new body stream
if
(
typeof
options
?.
progressCallback
===
"
function
"
)
{
const
contentLength
=
parseInt
(
response
.
headers
.
get
(
"
content-length
"
)
||
"
0
"
,
10
);
let
bytesRead
=
0
;
const
reader
=
clonedResponse
.
body
!
.
getReader
();
while
(
true
)
{
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
{
break
;
}
bytesRead
+=
value
.
length
;
const
progress
=
(
bytesRead
/
contentLength
)
*
100
;
options
?.
progressCallback
(
progress
);
}
}
return
response
;
}
src/middleware/sqlite.ts
View file @
c53d5c21
...
@@ -9,6 +9,7 @@ import initSqlJs, { Database } from "sql.js";
...
@@ -9,6 +9,7 @@ import initSqlJs, { Database } from "sql.js";
import
{
CardData
,
CardMeta
,
CardText
}
from
"
@/api/cards
"
;
import
{
CardData
,
CardMeta
,
CardText
}
from
"
@/api/cards
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
pfetch
}
from
"
@/infra
"
;
const
NeosConfig
=
useConfig
();
const
NeosConfig
=
useConfig
();
...
@@ -26,6 +27,7 @@ export interface sqliteAction {
...
@@ -26,6 +27,7 @@ export interface sqliteAction {
// 初始化DB需要业务方传入的数据
// 初始化DB需要业务方传入的数据
initInfo
?:
{
initInfo
?:
{
dbUrl
:
string
;
dbUrl
:
string
;
progressCallback
?:
(
progress
:
number
)
=>
void
;
// 用于获取读取进度
};
};
// 需要读取卡牌数据的ID
// 需要读取卡牌数据的ID
payload
?:
{
payload
?:
{
...
@@ -51,7 +53,9 @@ export default async function (action: sqliteAction): Promise<sqliteResult> {
...
@@ -51,7 +53,9 @@ export default async function (action: sqliteAction): Promise<sqliteResult> {
case
sqliteCmd
.
INIT
:
{
case
sqliteCmd
.
INIT
:
{
const
info
=
action
.
initInfo
;
const
info
=
action
.
initInfo
;
if
(
info
)
{
if
(
info
)
{
const
dataPromise
=
fetch
(
info
.
dbUrl
).
then
((
res
)
=>
res
.
arrayBuffer
());
// TODO: i18n
const
dataPromise
=
pfetch
(
info
.
dbUrl
,
{
progressCallback
:
action
.
initInfo
?.
progressCallback
,
}).
then
((
res
)
=>
res
.
arrayBuffer
());
// TODO: i18n
const
[
SQL
,
buffer
]
=
await
Promise
.
all
([
sqlPromise
,
dataPromise
]);
const
[
SQL
,
buffer
]
=
await
Promise
.
all
([
sqlPromise
,
dataPromise
]);
YGODB
=
new
SQL
.
Database
(
new
Uint8Array
(
buffer
));
YGODB
=
new
SQL
.
Database
(
new
Uint8Array
(
buffer
));
...
...
src/stores/initStore.ts
View file @
c53d5c21
...
@@ -8,6 +8,7 @@ export const initStore = proxy({
...
@@ -8,6 +8,7 @@ export const initStore = proxy({
},
},
decks
:
false
,
decks
:
false
,
i18n
:
false
,
i18n
:
false
,
wasm
:
false
,
// ...
// ...
reset
()
{},
reset
()
{},
}
satisfies
NeosStore
);
}
satisfies
NeosStore
);
src/ui/Layout/index.module.scss
View file @
c53d5c21
...
@@ -10,10 +10,20 @@
...
@@ -10,10 +10,20 @@
.logo-container
{
.logo-container
{
align-items
:
center
;
align-items
:
center
;
height
:
min-content
;
height
:
min-content
;
padding
:
5px
10px
;
background-color
:
hsl
(
0
,
0%
,
100%
,
0
);
transition
:
0
.2s
;
border-radius
:
20px
;
.logo
{
.logo
{
width
:
60px
;
width
:
60px
;
filter
:
brightness
(
1
.5
);
transform
:
translateY
(
1px
);
transform
:
translateY
(
1px
);
transition
:
0
.2s
;
}
&
:hover
{
background-color
:
hsl
(
0
,
0%
,
100%
,
0
.9
);
.logo
{
filter
:
invert
(
1
);
}
}
}
}
}
...
...
src/ui/Layout/index.tsx
View file @
c53d5c21
import
{
Avatar
}
from
"
antd
"
;
import
{
Avatar
}
from
"
antd
"
;
import
{
useEffect
}
from
"
react
"
;
import
{
import
{
type
LoaderFunction
,
type
LoaderFunction
,
NavLink
,
NavLink
,
...
@@ -7,30 +8,35 @@ import {
...
@@ -7,30 +8,35 @@ import {
}
from
"
react-router-dom
"
;
}
from
"
react-router-dom
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
CookieKeys
,
getCookie
}
from
"
@/api
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
accountStore
,
deckStore
,
initStore
,
type
User
}
from
"
@/stores
"
;
import
{
accountStore
}
from
"
@/stores
"
;
import
styles
from
"
./index.module.scss
"
;
import
styles
from
"
./index.module.scss
"
;
import
{
initSqlite
}
from
"
./utils
"
;
import
{
getLoginStatus
,
handleSSOLogin
,
initDeck
,
initSqlite
,
initWASM
,
}
from
"
./utils
"
;
const
NeosConfig
=
useConfig
();
const
NeosConfig
=
useConfig
();
export
const
loader
:
LoaderFunction
=
async
()
=>
{
export
const
loader
:
LoaderFunction
=
async
()
=>
{
const
user
=
getCookie
<
User
>
(
CookieKeys
.
USER
);
getLoginStatus
();
if
(
user
)
accountStore
.
login
(
user
);
initDeck
();
// 加载卡组
initSqlite
();
if
(
!
initStore
.
decks
)
initWASM
();
deckStore
.
initialize
().
then
(()
=>
(
initStore
.
decks
=
true
));
// 加载ygodb
if
(
!
initStore
.
sqlite
.
progress
)
{
initSqlite
().
then
(()
=>
(
initStore
.
sqlite
.
progress
=
1
));
initStore
.
sqlite
.
progress
=
0.01
;
}
return
null
;
return
null
;
};
};
export
const
Component
=
()
=>
{
export
const
Component
=
()
=>
{
// 捕获SSO登录
const
location
=
useLocation
();
useEffect
(()
=>
{
location
.
search
&&
handleSSOLogin
(
location
.
search
);
},
[
location
.
search
]);
// TODO 根据是否登录,显示内容
// TODO 根据是否登录,显示内容
const
{
pathname
}
=
useLocation
();
const
{
pathname
}
=
useLocation
();
const
pathnamesHideHeader
=
[
"
/waitroom
"
];
const
pathnamesHideHeader
=
[
"
/waitroom
"
];
...
@@ -45,11 +51,6 @@ export const Component = () => {
...
@@ -45,11 +51,6 @@ export const Component = () => {
alt=
"NEOS"
alt=
"NEOS"
/>
/>
</
div
>
</
div
>
{
/* <img
className={styles.logo}
src={`${NeosConfig.assetsPath}/neos-logo.svg`}
alt="NEOS"
/> */
}
<
NavLink
to=
"/"
>
主页
</
NavLink
>
<
NavLink
to=
"/"
>
主页
</
NavLink
>
<
NavLink
to=
"/match"
>
匹配
</
NavLink
>
<
NavLink
to=
"/match"
>
匹配
</
NavLink
>
<
NavLink
to=
"/build"
>
组卡
</
NavLink
>
<
NavLink
to=
"/build"
>
组卡
</
NavLink
>
...
...
src/ui/Layout/utils.ts
View file @
c53d5c21
import
rustInit
from
"
rust-src
"
;
import
{
CookieKeys
,
getCookie
,
setCookie
}
from
"
@/api
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useEnv
}
from
"
@/hook
"
;
import
sqliteMiddleWare
,
{
sqliteCmd
}
from
"
@/middleware/sqlite
"
;
import
sqliteMiddleWare
,
{
sqliteCmd
}
from
"
@/middleware/sqlite
"
;
import
{
initStore
}
from
"
@/stores
"
;
import
{
accountStore
,
deckStore
,
initStore
,
type
User
}
from
"
@/stores
"
;
const
{
cardsDbUrl
}
=
useConfig
();
const
{
cardsDbUrl
}
=
useConfig
();
const
{
BASE_URL
}
=
useEnv
();
/** 加载ygodb */
export
const
initSqlite
=
async
()
=>
{
export
const
initSqlite
=
async
()
=>
{
const
{
sqlite
}
=
initStore
;
if
(
!
initStore
.
sqlite
.
progress
)
{
sqlite
.
progress
=
0.01
;
const
{
sqlite
}
=
initStore
;
await
sqliteMiddleWare
({
const
progressCallback
=
(
progress
:
number
)
=>
cmd
:
sqliteCmd
.
INIT
,
(
sqlite
.
progress
=
progress
*
0.9
);
initInfo
:
{
dbUrl
:
cardsDbUrl
},
sqlite
.
progress
=
0.01
;
});
await
sqliteMiddleWare
({
sqlite
.
progress
=
1
;
cmd
:
sqliteCmd
.
INIT
,
initInfo
:
{
dbUrl
:
cardsDbUrl
,
progressCallback
},
});
sqlite
.
progress
=
1
;
}
};
/** 加载卡组 */
export
const
initDeck
=
async
()
=>
{
if
(
!
initStore
.
decks
)
{
await
deckStore
.
initialize
();
initStore
.
decks
=
true
;
}
};
/** 加载WASM */
export
const
initWASM
=
async
()
=>
{
const
url
=
BASE_URL
===
"
/
"
?
undefined
:
new
URL
(
"
rust_src_bg.wasm
"
,
`
${
BASE_URL
}
assets/`
);
await
rustInit
(
url
);
initStore
.
wasm
=
true
;
};
/** sso登录跳转回来 */
export
const
handleSSOLogin
=
async
(
search
:
string
)
=>
{
/** 从SSO跳转回的URL之中,解析用户信息 */
function
getSSOUser
(
searchParams
:
URLSearchParams
):
User
{
return
Object
.
fromEntries
(
searchParams
)
as
unknown
as
User
;
}
const
sso
=
new
URLSearchParams
(
search
).
get
(
"
sso
"
);
const
user
=
sso
?
getSSOUser
(
new
URLSearchParams
(
atob
(
sso
)))
:
undefined
;
if
(
user
)
{
accountStore
.
login
(
user
);
setCookie
(
CookieKeys
.
USER
,
JSON
.
stringify
(
user
));
// TODO: toast显示登录成功
}
};
/** 从cookie获取登录态 */
export
const
getLoginStatus
=
async
()
=>
{
const
user
=
getCookie
<
User
>
(
CookieKeys
.
USER
);
if
(
user
)
accountStore
.
login
(
user
);
};
};
src/ui/Match/index.tsx
View file @
c53d5c21
import
{
EditFilled
,
SettingFilled
}
from
"
@ant-design/icons
"
;
import
{
EditFilled
,
SettingFilled
}
from
"
@ant-design/icons
"
;
import
{
Space
}
from
"
antd
"
;
import
{
Space
}
from
"
antd
"
;
import
{
useEffect
,
useState
}
from
"
react
"
;
import
{
useEffect
,
useState
}
from
"
react
"
;
import
{
type
LoaderFunction
,
useNavigate
}
from
"
react-router-dom
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
CookieKeys
,
setCookie
}
from
"
@/api
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
accountStore
,
deckStore
,
IDeck
,
roomStore
,
type
User
}
from
"
@/stores
"
;
import
{
accountStore
,
deckStore
,
IDeck
,
roomStore
}
from
"
@/stores
"
;
import
{
Background
,
IconFont
,
Select
}
from
"
@/ui/Shared
"
;
import
{
Background
,
IconFont
,
Select
}
from
"
@/ui/Shared
"
;
import
styles
from
"
./index.module.scss
"
;
import
styles
from
"
./index.module.scss
"
;
...
@@ -14,17 +13,6 @@ import { MatchModal, matchStore } from "./MatchModal";
...
@@ -14,17 +13,6 @@ import { MatchModal, matchStore } from "./MatchModal";
import
{
ReplayModal
,
replayOpen
}
from
"
./ReplayModal
"
;
import
{
ReplayModal
,
replayOpen
}
from
"
./ReplayModal
"
;
import
{
init
}
from
"
./util
"
;
import
{
init
}
from
"
./util
"
;
export
const
loader
:
LoaderFunction
=
()
=>
{
const
sso
=
new
URLSearchParams
(
location
.
search
).
get
(
"
sso
"
);
const
user
=
sso
?
getSSOUser
(
new
URLSearchParams
(
atob
(
sso
)))
:
undefined
;
if
(
user
)
{
accountStore
.
login
(
user
);
setCookie
(
CookieKeys
.
USER
,
JSON
.
stringify
(
user
));
// TODO: toast显示登录成功
}
return
null
;
};
const
NeosConfig
=
useConfig
();
const
NeosConfig
=
useConfig
();
export
const
Component
:
React
.
FC
=
()
=>
{
export
const
Component
:
React
.
FC
=
()
=>
{
...
@@ -150,8 +138,3 @@ const Mode: React.FC<{
...
@@ -150,8 +138,3 @@ const Mode: React.FC<{
<
div
className=
{
styles
.
desc
}
>
{
desc
}
</
div
>
<
div
className=
{
styles
.
desc
}
>
{
desc
}
</
div
>
</
div
>
</
div
>
);
);
/** 从SSO跳转回的URL之中,解析用户信息 */
function
getSSOUser
(
searchParams
:
URLSearchParams
):
User
{
return
Object
.
fromEntries
(
searchParams
)
as
unknown
as
User
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment