Skip to content

Commit 5dd74ba

Browse files
authored
Merge pull request #240 from DakaraProject/fix/player-token-reload
Fix player token box on page reload
2 parents 3f24f38 + e257673 commit 5dd74ba

3 files changed

Lines changed: 129 additions & 100 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
- Fixed empty player token dialog if no player token exists.
4646
- Fixed incorrect form when creating a player token.
47+
- Fixed player token box not displayed on page refresh.
4748

4849
## 1.9.2 - 2025-03-22
4950

src/components/settings/Tokens.jsx

Lines changed: 116 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,17 @@ import TokenWidget from 'components/generics/TokenWidget'
1414
import { IsLibraryManager } from 'permissions/components/Library'
1515
import { IsPlaylistManager } from 'permissions/components/Playlist'
1616
import { Status } from 'reducers/alterationsResponse'
17+
import { karaokePropType, playerTokenPropType } from 'serverPropTypes/playlist'
1718
import { CSSTransitionLazy } from 'thirdpartyExtensions/ReactTransitionGroup'
1819

19-
function PlayerTokenBox() {
20-
const playerTokenState = useSelector((state) => state.playlist.playerToken)
21-
const responseOfCreatePlayerToken = useSelector(
22-
(state) => state.alterationsResponse.unique.createPlayerToken
23-
)
20+
function PlayerTokenBoxDisplay({ playerToken, karaoke }) {
2421
const responseOfRevokePlayerToken = useSelector(
2522
(state) => state.alterationsResponse.unique.revokePlayerToken
2623
)
27-
const karaokeState = useSelector((state) => state.playlist.karaoke)
28-
29-
const [confirmDisplayed, setConfirmDisplayed] = useState(false)
3024

3125
const dispatch = useDispatch()
3226

33-
const { data: karaoke } = karaokeState
34-
35-
useEffect(
36-
() => {
37-
// load player token as soon as the karaoke ID has been fetched
38-
if (!playerTokenState.status && karaoke.id) {
39-
dispatch(loadPlayerToken(karaoke.id))
40-
}
41-
},
42-
// eslint-disable-next-line react-hooks/exhaustive-deps
43-
[]
44-
)
27+
const [confirmDisplayed, setConfirmDisplayed] = useState(false)
4528

4629
const displayConfirm = useCallback(() => {
4730
setConfirmDisplayed(true)
@@ -51,82 +34,111 @@ function PlayerTokenBox() {
5134
setConfirmDisplayed(false)
5235
}, [])
5336

54-
const doConfirm = useCallback(
55-
() => {
56-
clearConfirm()
57-
dispatch(revokePlayerToken(karaoke.id))
58-
},
59-
// eslint-disable-next-line react-hooks/exhaustive-deps
60-
[karaoke]
37+
return (
38+
<div className="player-token-box-display flow">
39+
<TokenWidget token={playerToken.key} />
40+
<div className="ribbon info copy-help">
41+
<p className="message">
42+
You can use this token to authenticate the player.
43+
</p>
44+
</div>
45+
<div className="revoke controls notifiable">
46+
<CSSTransitionLazy
47+
in={confirmDisplayed}
48+
classNames="notified"
49+
timeout={{
50+
enter: 300,
51+
exit: 150,
52+
}}
53+
>
54+
<ConfirmationBar
55+
onConfirm={() => {
56+
dispatch(revokePlayerToken(karaoke.id))
57+
}}
58+
onCancel={clearConfirm}
59+
/>
60+
</CSSTransitionLazy>
61+
<Notification
62+
alterationResponse={responseOfRevokePlayerToken}
63+
pendingMessage={null}
64+
successfulMessage={null}
65+
failedMessage="Unable to revoke player token"
66+
/>
67+
<button className="control primary" onClick={displayConfirm}>
68+
Revoke player token
69+
</button>
70+
</div>
71+
</div>
6172
)
73+
}
74+
75+
PlayerTokenBoxDisplay.propTypes = {
76+
playerToken: playerTokenPropType.isRequired,
77+
karaoke: karaokePropType.isRequired,
78+
}
79+
80+
function PlayerTokenBoxCreate({ karaoke }) {
81+
const responseOfCreatePlayerToken = useSelector(
82+
(state) => state.alterationsResponse.unique.createPlayerToken
83+
)
84+
85+
const dispatch = useDispatch()
86+
87+
return (
88+
<div className="player-token-box-create flow">
89+
<p>Create a token that can be used to authenticate the player.</p>
90+
<div className="controls notifiable">
91+
<Notification
92+
alterationResponse={responseOfCreatePlayerToken}
93+
pendingMessage={null}
94+
successfulMessage={null}
95+
failedMessage="Unable to create player token"
96+
/>
97+
<button
98+
className="control primary"
99+
onClick={() => {
100+
dispatch(createPlayerToken(karaoke.id))
101+
}}
102+
>
103+
Create player token
104+
</button>
105+
</div>
106+
</div>
107+
)
108+
}
109+
110+
PlayerTokenBoxCreate.propTypes = {
111+
karaoke: karaokePropType.isRequired,
112+
}
113+
114+
function PlayerTokenBox() {
115+
const playerTokenState = useSelector((state) => state.playlist.playerToken)
116+
const karaokeState = useSelector((state) => state.playlist.karaoke)
117+
118+
const dispatch = useDispatch()
119+
120+
const { data: karaoke } = karaokeState
121+
const { id: karaokeId } = karaoke
62122

63123
const { data: playerToken, status: playerTokenStatus } = playerTokenState
64124
const keyExists = !!playerToken.key
65125

66-
// NOTE If the token is not found, the state is still `successful` as this
126+
useEffect(
127+
() => {
128+
// load player token as soon as the karaoke ID has been fetched
129+
if (!playerTokenStatus && karaokeId) {
130+
dispatch(loadPlayerToken(karaokeId))
131+
}
132+
},
133+
// eslint-disable-next-line react-hooks/exhaustive-deps
134+
[playerTokenStatus, karaokeId]
135+
)
136+
137+
// NOTE If the token is not found, the status is still `successful` as this
67138
// is a valid case. Check the reducer to see how this case is handled.
68139

69140
let playerTokenBox
70141
if (playerTokenStatus === Status.successful) {
71-
let playerTokenBoxContent
72-
if (keyExists) {
73-
// display token
74-
playerTokenBoxContent = (
75-
<>
76-
<TokenWidget token={playerToken.key} />
77-
<div className="ribbon info copy-help">
78-
<p className="message">
79-
You can use this token to authenticate the player.
80-
</p>
81-
</div>
82-
<div className="revoke controls notifiable">
83-
<CSSTransitionLazy
84-
in={confirmDisplayed}
85-
classNames="notified"
86-
timeout={{
87-
enter: 300,
88-
exit: 150,
89-
}}
90-
>
91-
<ConfirmationBar onConfirm={doConfirm} onCancel={clearConfirm} />
92-
</CSSTransitionLazy>
93-
<Notification
94-
alterationResponse={responseOfRevokePlayerToken}
95-
pendingMessage={null}
96-
successfulMessage={null}
97-
failedMessage="Unable to revoke player token"
98-
/>
99-
<button className="control primary" onClick={displayConfirm}>
100-
Revoke player token
101-
</button>
102-
</div>
103-
</>
104-
)
105-
} else {
106-
// display button to create token
107-
playerTokenBoxContent = (
108-
<>
109-
<p>Create a token that can be used to authenticate the player.</p>
110-
<div className="controls notifiable">
111-
<button
112-
className="control primary"
113-
onClick={() => {
114-
dispatch(createPlayerToken(karaoke.id))
115-
}}
116-
>
117-
Create player token
118-
</button>
119-
</div>
120-
<Notification
121-
alterationResponse={responseOfCreatePlayerToken}
122-
pendingMessage={null}
123-
successfulMessage={null}
124-
failedMessage="Unable to create player token"
125-
/>
126-
</>
127-
)
128-
}
129-
130142
playerTokenBox = (
131143
<CSSTransition
132144
in={keyExists}
@@ -136,7 +148,11 @@ function PlayerTokenBox() {
136148
exit: 150,
137149
}}
138150
>
139-
{playerTokenBoxContent}
151+
{keyExists ? (
152+
<PlayerTokenBoxDisplay playerToken={playerToken} karaoke={karaoke} />
153+
) : (
154+
<PlayerTokenBoxCreate karaoke={karaoke} />
155+
)}
140156
</CSSTransition>
141157
)
142158
} else if (playerTokenStatus === Status.failed) {
@@ -145,6 +161,12 @@ function PlayerTokenBox() {
145161
<p>Unable to get player token.</p>
146162
</div>
147163
)
164+
} else {
165+
playerTokenBox = (
166+
<div className="ribbon">
167+
<p>Pending…</p>
168+
</div>
169+
)
148170
}
149171

150172
return (
@@ -204,16 +226,16 @@ export default function Tokens() {
204226
onCancel={clearConfirm}
205227
/>
206228
</CSSTransitionLazy>
229+
<Notification
230+
alterationResponse={responseOfRevokeToken}
231+
pendingMessage={null}
232+
successfulMessage={null}
233+
failedMessage="Unable to revoke token"
234+
/>
207235
<button className="control primary" onClick={displayConfirm}>
208236
Revoke token
209237
</button>
210238
</div>
211-
<Notification
212-
alterationResponse={responseOfRevokeToken}
213-
pendingMessage={null}
214-
successfulMessage={null}
215-
failedMessage="Unable to revoke token"
216-
/>
217239
</div>
218240
<IsPlaylistManager user={user}>
219241
<PlayerTokenBox />

src/style/components/settings/_tokens.scss

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,30 @@
99

1010
#tokens {
1111
.token-box {
12+
// approximate min and max height
13+
$token-player-min-height: calc(
14+
1.25em + sizes.$row-height + sizes.$gap-vertical
15+
);
16+
$token-player-max-height: calc(
17+
3 * sizes.$row-height + 2 * sizes.$gap-vertical
18+
);
19+
1220
.token-player-enter {
13-
// approximate min and max height
14-
height: calc(2em + sizes.$row-height + sizes.$gap-vertical);
21+
height: $token-player-min-height;
1522
overflow-y: hidden;
1623

1724
&.token-player-enter-active {
18-
height: 2 * sizes.$row-height + 2 * sizes.$gap-vertical;
25+
height: $token-player-max-height;
1926
transition: height 300ms ease-out;
2027
}
2128
}
2229

2330
.token-player-exit {
24-
// approximate min and max height
25-
height: 2 * sizes.$row-height + 2 * sizes.$gap-vertical;
31+
height: $token-player-max-height;
2632
overflow-y: hidden;
2733

2834
&.token-player-exit-active {
29-
height: calc(2em + sizes.$row-height + sizes.$gap-vertical);
35+
height: $token-player-min-height;
3036
transition: height 150ms ease-out;
3137
}
3238
}

0 commit comments

Comments
 (0)