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
875e48fc
Commit
875e48fc
authored
Jul 09, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: timer
parent
00aa816c
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
109 additions
and
87 deletions
+109
-87
src/config/defaults.ts
src/config/defaults.ts
+1
-1
src/styles/core.scss
src/styles/core.scss
+5
-1
src/ui/Duel/Main.tsx
src/ui/Duel/Main.tsx
+1
-2
src/ui/Duel/PlayMat/Card/index.tsx
src/ui/Duel/PlayMat/Card/index.tsx
+1
-1
src/ui/Duel/PlayMat/LifeBar/index.scss
src/ui/Duel/PlayMat/LifeBar/index.scss
+21
-5
src/ui/Duel/PlayMat/LifeBar/index.tsx
src/ui/Duel/PlayMat/LifeBar/index.tsx
+79
-17
src/ui/Duel/PlayMat/Menu/index.tsx
src/ui/Duel/PlayMat/Menu/index.tsx
+1
-0
src/ui/Duel/PlayMat/Timer/index.scss
src/ui/Duel/PlayMat/Timer/index.scss
+0
-25
src/ui/Duel/PlayMat/Timer/index.tsx
src/ui/Duel/PlayMat/Timer/index.tsx
+0
-34
src/ui/Duel/PlayMat/index.ts
src/ui/Duel/PlayMat/index.ts
+0
-1
No files found.
src/config/defaults.ts
View file @
875e48fc
...
...
@@ -19,7 +19,7 @@ const defaultConfig: DefaultsConfig = {
const
aiModeConfig
:
DefaultsConfig
=
{
...
defaultConfig
,
defaultDeck
:
VITE_AI_MODE_DEFAULT_DECK
||
"
Hero
"
,
defaultPlayer
:
`AiKiller
${
Math
.
random
().
toString
(
36
).
slice
(
2
)}
}`
,
defaultPlayer
:
`AiKiller
-
${
Math
.
random
().
toString
(
36
).
slice
(
2
,
6
)}
}`
,
defaultPassword
:
"
AI
"
,
};
...
...
src/styles/core.scss
View file @
875e48fc
...
...
@@ -41,7 +41,11 @@ body {
margin
:
0
;
place-items
:
center
;
min-width
:
320px
;
min-height
:
100vh
;
position
:
fixed
;
top
:
0
;
bottom
:
0
;
left
:
0
;
right
:
0
;
}
a
{
...
...
src/ui/Duel/Main.tsx
View file @
875e48fc
...
...
@@ -14,7 +14,7 @@ import {
SortCardModal
,
YesNoModal
,
}
from
"
./Message
"
;
import
{
LifeBar
,
Mat
,
Menu
,
Timer
}
from
"
./PlayMat
"
;
import
{
LifeBar
,
Mat
,
Menu
}
from
"
./PlayMat
"
;
const
NeosDuel
=
()
=>
{
return
(
...
...
@@ -23,7 +23,6 @@ const NeosDuel = () => {
<
Alert
/>
<
Menu
/>
<
LifeBar
/>
<
Timer
/>
<
Mat
/>
<
CardModal
/>
<
CardListModal
/>
...
...
src/ui/Duel/PlayMat/Card/index.tsx
View file @
875e48fc
...
...
@@ -3,7 +3,7 @@ import "./index.scss";
import
{
animated
,
to
,
useSpring
}
from
"
@react-spring/web
"
;
import
{
Dropdown
,
type
MenuProps
}
from
"
antd
"
;
import
classnames
from
"
classnames
"
;
import
React
,
{
type
CSSProperties
,
useEffect
,
use
State
,
useRef
}
from
"
react
"
;
import
React
,
{
type
CSSProperties
,
useEffect
,
use
Ref
,
useState
}
from
"
react
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
type
{
CardMeta
}
from
"
@/api
"
;
...
...
src/ui/Duel/PlayMat/LifeBar/index.scss
View file @
875e48fc
...
...
@@ -3,20 +3,23 @@
display
:
flex
;
top
:
0
;
left
:
0
;
height
:
100vh
;
// FIXME: 100% on safari
bottom
:
0
;
flex-direction
:
column
;
justify-content
:
space-between
;
padding
:
20px
35px
;
padding
:
20px
;
margin-left
:
10px
;
pointer-events
:
none
;
z-index
:
100
;
--bg-color
:
#323232
;
width
:
200px
;
}
.life-bar
{
width
:
160px
;
position
:
relative
;
width
:
100%
;
color
:
white
;
background-color
:
#323232
;
background-color
:
var
(
--
bg-color
)
;
font-family
:
var
(
--
theme-font
);
border
:
1px
solid
#222
;
padding
:
1rem
;
padding-bottom
:
0
.6rem
;
border-radius
:
8px
;
...
...
@@ -32,3 +35,16 @@
font-size
:
1
.8rem
;
}
}
.timer-container
{
background-color
:
var
(
--
bg-color
);
border-radius
:
4px
;
padding
:
0
.4rem
1rem
;
font-size
:
0
.8rem
;
font-weight
:
bold
;
font-family
:
var
(
--
theme-font
);
width
:
fit-content
;
color
:
white
;
display
:
flex
;
gap
:
8px
;
align-items
:
center
;
}
src/ui/Duel/PlayMat/LifeBar/index.tsx
View file @
875e48fc
import
"
./index.scss
"
;
import
{
Progress
,
Space
}
from
"
antd
"
;
import
classNames
from
"
classnames
"
;
import
React
,
{
useEffect
}
from
"
react
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
AnimatedNumbers
from
"
react-animated-numbers
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
useEnv
}
from
"
@/hook
"
;
import
{
matStore
,
playerStore
}
from
"
@/stores
"
;
// 三个候选方案
// https://snack.expo.dev/?platform=web
// https://github.com/heyman333/react-animated-numbers
...
...
@@ -28,28 +29,89 @@ export const LifeBar: React.FC = () => {
setOpLife
(
snap
.
op
.
life
);
},
[
snap
.
op
.
life
]);
const
snapTimeLimit
=
useSnapshot
(
matStore
.
timeLimits
);
const
[
myTimeLimit
,
setMyTimeLimit
]
=
useState
(
snapTimeLimit
.
me
);
const
[
opTimeLimit
,
setOpTimeLimit
]
=
useState
(
snapTimeLimit
.
op
);
useEffect
(()
=>
{
setMyTimeLimit
(
snapTimeLimit
.
me
);
},
[
snapTimeLimit
.
me
]);
useEffect
(()
=>
{
setOpTimeLimit
(
snapTimeLimit
.
op
);
},
[
snapTimeLimit
.
op
]);
useEffect
(()
=>
{
setInterval
(()
=>
{
setMyTimeLimit
((
time
)
=>
time
-
1
);
setOpTimeLimit
((
time
)
=>
time
-
1
);
},
1000
);
},
[]);
useEffect
(()
=>
{
if
(
useEnv
().
VITE_IS_AI_MODE
)
{
// 如果是AI模式
// FIXME: 探索一个优雅的、判断当前是不是AI模式的方法,用户手动输入AI也是AI模式
setMyTimeLimit
(
240
);
setOpTimeLimit
(
240
);
}
},
[
currentPlayer
]);
return
(
<
div
id=
"life-bar-container"
>
<
LifeBarItem
active=
{
!
matStore
.
isMe
(
currentPlayer
)
}
name=
{
snapPlayer
.
getOpPlayer
().
name
??
"
?
"
}
life=
{
opLife
}
timeLimit=
{
opTimeLimit
}
isMe=
{
false
}
/>
<
LifeBarItem
active=
{
matStore
.
isMe
(
currentPlayer
)
}
name=
{
snapPlayer
.
getMePlayer
().
name
??
"
?
"
}
life=
{
meLife
}
timeLimit=
{
myTimeLimit
}
isMe=
{
true
}
/>
</
div
>
);
};
const
LifeBarItem
:
React
.
FC
<
{
active
:
boolean
;
name
:
string
;
life
:
number
;
timeLimit
:
number
;
isMe
:
boolean
;
}
>
=
({
active
,
name
,
life
,
timeLimit
,
isMe
})
=>
{
const
mm
=
Math
.
floor
(
timeLimit
/
60
);
const
ss
=
timeLimit
%
60
;
const
timeText
=
`
${
mm
<
10
?
"
0
"
+
mm
:
mm
}
:
${
ss
<
10
?
"
0
"
+
ss
:
ss
}
`
;
return
(
<
Space
direction=
"vertical"
style=
{
{
flexDirection
:
isMe
?
"
column-reverse
"
:
"
column
"
,
}
}
size=
{
12
}
>
<
div
className=
{
classNames
(
"
life-bar
"
,
{
"
life-bar-activated
"
:
matStore
.
isMe
(
currentPlayer
)
,
"
life-bar-activated
"
:
active
,
})
}
>
<
div
className=
"name"
>
{
snapPlayer
.
getOpPlayer
().
name
}
</
div
>
<
div
className=
"life"
>
{
<
AnimatedNumbers
animateToNumber=
{
opLife
}
/>
}
</
div
>
<
div
className=
"name"
>
{
name
}
</
div
>
<
div
className=
"life"
>
{
<
AnimatedNumbers
animateToNumber=
{
life
}
/>
}
</
div
>
</
div
>
<
div
className=
{
classNames
(
"
life-bar
"
,
{
"
life-bar-activated
"
:
matStore
.
isMe
(
currentPlayer
),
})
}
>
<
div
className=
"name"
>
{
snapPlayer
.
getMePlayer
().
name
}
</
div
>
<
div
className=
"life"
>
<
AnimatedNumbers
animateToNumber=
{
meLife
}
/>
{
active
&&
(
<
div
className=
"timer-container"
>
<
Progress
type=
"circle"
percent=
{
(
timeLimit
/
240
)
*
100
}
strokeWidth=
{
20
}
size=
{
14
}
/>
<
div
className=
"timer-text"
>
{
timeText
}
</
div
>
</
div
>
</
div
>
</
div
>
)
}
</
Space
>
);
};
src/ui/Duel/PlayMat/Menu/index.tsx
View file @
875e48fc
...
...
@@ -28,6 +28,7 @@ import {
}
from
"
@/api
"
;
import
{
cardStore
,
matStore
}
from
"
@/stores
"
;
import
PhaseType
=
ygopro
.
StocGameMessage
.
MsgNewPhase
.
PhaseType
;
import
{
Timer
}
from
"
../Timer
"
;
const
{
phase
}
=
matStore
;
const
{
useToken
}
=
theme
;
...
...
src/ui/Duel/PlayMat/Timer/index.scss
deleted
100644 → 0
View file @
00aa816c
#timer-container
{
position
:
fixed
;
display
:
flex
;
top
:
0
;
right
:
0
;
height
:
100vh
;
padding
:
20px
35px
;
flex-direction
:
column
;
pointer-events
:
none
;
}
.timer
{
width
:
100px
;
color
:
white
;
background-color
:
#323232
;
font-family
:
var
(
--
theme-font
);
border
:
1px
solid
#222
;
padding
:
1rem
;
padding-bottom
:
0
.6rem
;
border-radius
:
8px
;
text-align
:
center
;
display
:
flex
;
flex-direction
:
column
;
font-size
:
1
.2rem
;
}
src/ui/Duel/PlayMat/Timer/index.tsx
deleted
100644 → 0
View file @
00aa816c
import
"
./index.scss
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
matStore
}
from
"
@/stores
"
;
export
const
Timer
:
React
.
FC
=
()
=>
{
const
[
time
,
setTime
]
=
useState
(
0
);
const
snap
=
useSnapshot
(
matStore
);
useEffect
(()
=>
{
const
interval
=
setInterval
(()
=>
{
if
(
time
>
0
)
{
setTime
((
time
)
=>
time
-
1
);
}
},
1000
);
return
()
=>
clearInterval
(
interval
);
},
[
time
]);
useEffect
(()
=>
{
setTime
(
snap
.
timeLimits
.
me
);
},
[
snap
.
timeLimits
.
me
]);
useEffect
(()
=>
{
setTime
(
snap
.
timeLimits
.
op
);
},
[
snap
.
timeLimits
.
op
]);
return
(
<
div
id=
"timer-container"
>
<
div
className=
"timer"
>
{
time
}
</
div
>
</
div
>
);
};
src/ui/Duel/PlayMat/index.ts
View file @
875e48fc
export
*
from
"
./LifeBar
"
;
export
*
from
"
./Mat
"
;
export
*
from
"
./Menu
"
;
export
*
from
"
./Timer
"
;
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