@@ -16,10 +16,14 @@ import {
16
16
enderChatPrefix ,
17
17
sendMessageError
18
18
} from './packetHandler'
19
+ import { createConnection } from './sessionBuilder'
19
20
import globalStyle from '../../globalStyle'
20
21
import useDarkMode from '../../context/useDarkMode'
22
+ import AccountsContext from '../../context/accountsContext'
23
+ import ServersContext from '../../context/serversContext'
24
+ import useSessionStore from '../../context/sessionStore'
21
25
import SettingsContext from '../../context/settingsContext'
22
- import ConnectionContext from '../../context/connectionContext'
26
+ import ConnectionContext , { Connection } from '../../context/connectionContext'
23
27
import {
24
28
ChatToJsx ,
25
29
mojangColorMap ,
@@ -41,6 +45,8 @@ interface RootStackParamList {
41
45
}
42
46
type Props = NativeStackScreenProps < RootStackParamList , 'Chat' >
43
47
48
+ export type Status = 'OPENING' | 'CONNECTING' | 'CONNECTED' | 'CLOSED'
49
+
44
50
interface Message {
45
51
key : number
46
52
text : MinecraftChat
@@ -84,17 +90,26 @@ const handleError =
84
90
addMessage ( enderChatPrefix + translated )
85
91
}
86
92
93
+ const isConnection = ( connection : any ) : connection is Connection =>
94
+ ! ! ( connection as Connection ) . connection
95
+
87
96
// TODO: Ability to copy text.
88
97
const ChatScreen = ( { navigation, route } : Props ) => {
89
98
const darkMode = useDarkMode ( )
90
99
const { settings } = useContext ( SettingsContext )
91
- const { connection, setConnection } = useContext ( ConnectionContext )
100
+ const { servers } = useContext ( ServersContext )
101
+ const { accounts, setAccounts } = useContext ( AccountsContext )
102
+ const { connection, setConnection, setDisconnectReason } =
103
+ useContext ( ConnectionContext )
104
+ const { sessions, setSession } = useSessionStore ( )
92
105
// TODO: Show command history.
93
106
const [ , setCommandHistory ] = useState < string [ ] > ( [ ] )
94
107
const [ settingsOpen , setSettingsOpen ] = useState ( false )
95
108
const [ messages , setMessages ] = useState < Message [ ] > ( [ ] )
96
109
const [ loggedIn , setLoggedIn ] = useState ( false )
97
110
const [ message , setMessage ] = useState ( '' )
111
+ const healthRef = useRef < number | null > ( null )
112
+ const statusRef = useRef < Status > ( connection ? 'CONNECTING' : 'OPENING' )
98
113
const idRef = useRef ( 0 )
99
114
100
115
const charLimit =
@@ -106,17 +121,67 @@ const ChatScreen = ({ navigation, route }: Props) => {
106
121
const trunc = m . length > 500 ? m . slice ( 0 , 499 ) : m
107
122
return [ { key : idRef . current ++ , text } ] . concat ( trunc )
108
123
} )
124
+ const closeChatScreen = ( ) => {
125
+ if ( navigation . canGoBack ( ) && statusRef . current !== 'CLOSED' ) {
126
+ navigation . goBack ( )
127
+ }
128
+ }
129
+
130
+ // Screen cleanup function.
131
+ useEffect ( ( ) =>
132
+ navigation . addListener ( 'beforeRemove' , ( ) => {
133
+ statusRef . current = 'CLOSED'
134
+ // Gracefully disconnect on unmount, destroy will be called in 20s automatically if needed.
135
+ if ( connection ) {
136
+ connection . connection . close ( )
137
+ setConnection ( undefined )
138
+ }
139
+ } )
140
+ )
141
+
142
+ // Create connection useEffect.
143
+ useEffect ( ( ) => {
144
+ if ( statusRef . current === 'OPENING' ) {
145
+ statusRef . current = 'CONNECTING'
146
+ createConnection (
147
+ route . params . serverName ,
148
+ route . params . version ,
149
+ servers ,
150
+ settings ,
151
+ accounts ,
152
+ sessions ,
153
+ setSession ,
154
+ setAccounts ,
155
+ setConnection ,
156
+ setDisconnectReason ,
157
+ closeChatScreen
158
+ )
159
+ . then ( conn => {
160
+ console . log ( statusRef . current )
161
+ console . log ( isConnection ( conn ) )
162
+ if ( statusRef . current !== 'CLOSED' ) {
163
+ if ( isConnection ( conn ) ) setConnection ( conn )
164
+ else setDisconnectReason ( conn )
165
+ } else if ( isConnection ( conn ) ) conn . connection . close ( ) // No memory leaky
166
+ } )
167
+ . catch ( ( ) => {
168
+ closeChatScreen ( )
169
+ setDisconnectReason ( {
170
+ server : route . params . serverName ,
171
+ reason : 'An error occurred resolving the server hostname!'
172
+ } )
173
+ } )
174
+ }
175
+ } )
109
176
110
177
// Packet handler useEffect.
111
- const loggedInRef = useRef ( false )
112
- const healthRef = useRef < number | null > ( null )
113
178
useEffect ( ( ) => {
114
179
if ( ! connection ) return
115
180
connection . connection . on (
116
181
'packet' ,
117
182
packetHandler (
118
183
healthRef ,
119
- loggedInRef ,
184
+ statusRef ,
120
185
setLoggedIn ,
121
186
connection . connection ,
122
187
addMessage ,
@@ -138,19 +203,6 @@ const ChatScreen = ({ navigation, route }: Props) => {
138
203
settings . sendSpawnCommand
139
204
] )
140
205
141
- // Cleanup useEffect on unload.
142
- useEffect ( ( ) => {
143
- if ( ! connection ) {
144
- navigation . goBack ( ) // Safety net.
145
- return
146
- }
147
- return ( ) => {
148
- // Gracefully disconnect, destroy will be called in 20s automatically if needed.
149
- connection . connection . close ( )
150
- setConnection ( undefined )
151
- }
152
- } , [ connection , setConnection , navigation ] )
153
-
154
206
const sendMessage = ( msg : string , saveHistory : boolean ) => {
155
207
if ( ! connection || ! msg ) return
156
208
setMessage ( '' )
@@ -191,7 +243,6 @@ const ChatScreen = ({ navigation, route }: Props) => {
191
243
}
192
244
}
193
245
194
- if ( ! connection ) return < > </ > // This should never be hit hopefully.
195
246
const title =
196
247
route . params . serverName . length > 12
197
248
? route . params . serverName . substring ( 0 , 9 ) + '...'
@@ -203,7 +254,7 @@ const ChatScreen = ({ navigation, route }: Props) => {
203
254
iconStyle = { styles . backButtonIcon }
204
255
backgroundColor = '#363636'
205
256
onPress = { ( ) => {
206
- settingsOpen ? setSettingsOpen ( false ) : navigation . goBack ( )
257
+ settingsOpen ? setSettingsOpen ( false ) : closeChatScreen ( )
207
258
} }
208
259
/>
209
260
</ View >
@@ -223,7 +274,7 @@ const ChatScreen = ({ navigation, route }: Props) => {
223
274
onPress = { ( ) => setSettingsOpen ( true ) }
224
275
/>
225
276
</ View >
226
- { ! loggedIn && (
277
+ { ( ! loggedIn || ! connection ) && (
227
278
< View style = { styles . loadingScreen } >
228
279
< ActivityIndicator
229
280
color = '#00aaff'
@@ -235,7 +286,7 @@ const ChatScreen = ({ navigation, route }: Props) => {
235
286
< Text style = { styles . loadingScreenText } > Connecting...</ Text >
236
287
</ View >
237
288
) }
238
- { loggedIn && (
289
+ { loggedIn && connection && (
239
290
< >
240
291
< ChatMessageListMemo
241
292
messages = { messages }
0 commit comments