Skip to content

Commit 1942c40

Browse files
committed
Much better loading screen logic with feedback.
The loading screen now shows actual feedback of what's happening. If you close a connection, it won't connect if it was reloading premium.
1 parent afaaaa1 commit 1942c40

File tree

3 files changed

+105
-77
lines changed

3 files changed

+105
-77
lines changed

src/screens/chat/ChatScreen.tsx

+58-46
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ import {
1616
enderChatPrefix,
1717
sendMessageError
1818
} from './packetHandler'
19-
import { createConnection } from './sessionBuilder'
19+
import { getSession, createConnection } from './sessionBuilder'
2020
import { RootStackParamList } from '../../App'
2121
import globalStyle from '../../globalStyle'
2222
import useDarkMode from '../../context/useDarkMode'
2323
import AccountsContext from '../../context/accountsContext'
2424
import ServersContext from '../../context/serversContext'
2525
import useSessionStore from '../../context/sessionStore'
2626
import SettingsContext from '../../context/settingsContext'
27-
import ConnectionContext, { Connection } from '../../context/connectionContext'
27+
import ConnectionContext, {
28+
DisconnectReason
29+
} from '../../context/connectionContext'
2830
import {
2931
ChatToJsx,
3032
mojangColorMap,
@@ -85,9 +87,6 @@ const handleError =
8587
addMessage(enderChatPrefix + translated)
8688
}
8789

88-
const isConnection = (connection: any): connection is Connection =>
89-
!!(connection as Connection).connection
90-
9190
// TODO: Ability to copy text.
9291
const ChatScreen = ({ navigation, route }: Props) => {
9392
const darkMode = useDarkMode()
@@ -97,25 +96,27 @@ const ChatScreen = ({ navigation, route }: Props) => {
9796
const { connection, setConnection, setDisconnectReason } =
9897
useContext(ConnectionContext)
9998
const { sessions, setSession } = useSessionStore()
99+
100100
// TODO: Show command history.
101101
const [, setCommandHistory] = useState<string[]>([])
102102
const [messages, setMessages] = useState<Message[]>([])
103-
const [loggedIn, setLoggedIn] = useState(false)
103+
const [loading, setLoading] = useState('Connecting to server...')
104104
const [message, setMessage] = useState('')
105+
105106
const messagesBufferRef = useRef<Message[]>([])
106107
const healthRef = useRef<number | null>(null)
107108
const statusRef = useRef<Status>(connection ? 'CONNECTING' : 'OPENING')
108109
const idRef = useRef(0)
109110

110-
const charLimit =
111-
connection && connection.connection.options.protocolVersion >= 306 // 16w38a
112-
? 256
113-
: 100
111+
const { version, serverName } = route.params
112+
const charLimit = version >= 306 /* 16w38a */ ? 256 : 100
113+
114114
const addMessage = (text: MinecraftChat) =>
115115
messagesBufferRef.current.unshift({ key: idRef.current++, text })
116-
const closeChatScreen = () => {
117-
if (navigation.canGoBack() && statusRef.current !== 'CLOSED') {
118-
navigation.goBack()
116+
const closeChatScreen = (reason?: DisconnectReason) => {
117+
if (statusRef.current !== 'CLOSED') {
118+
if (navigation.canGoBack()) navigation.goBack()
119+
if (reason) setDisconnectReason(reason)
119120
}
120121
}
121122

@@ -149,36 +150,45 @@ const ChatScreen = ({ navigation, route }: Props) => {
149150
useEffect(() => {
150151
if (statusRef.current === 'OPENING') {
151152
statusRef.current = 'CONNECTING'
152-
createConnection(
153-
route.params.serverName,
154-
route.params.version,
155-
servers,
156-
settings,
157-
accounts,
158-
sessions,
159-
setSession,
160-
setAccounts,
161-
setConnection,
162-
setDisconnectReason,
163-
closeChatScreen
164-
)
165-
.then(conn => {
166-
if (statusRef.current !== 'CLOSED') {
167-
if (isConnection(conn)) setConnection(conn)
168-
else {
169-
closeChatScreen()
170-
setDisconnectReason(conn)
153+
;(async () => {
154+
const session = await getSession(
155+
version,
156+
accounts,
157+
sessions,
158+
setSession,
159+
setLoading,
160+
setAccounts
161+
)
162+
if (typeof session === 'string') {
163+
closeChatScreen({ server: serverName, reason: session })
164+
} else if (statusRef.current !== 'CLOSED') {
165+
setLoading('Connecting to server...')
166+
const conn = await createConnection(
167+
serverName,
168+
version,
169+
servers,
170+
session,
171+
settings,
172+
accounts,
173+
setConnection,
174+
closeChatScreen
175+
)
176+
if ((statusRef.current as 'CLOSED' | 'CONNECTING') !== 'CLOSED') {
177+
if (typeof conn === 'string') {
178+
closeChatScreen({ server: serverName, reason: conn })
179+
} else {
180+
setConnection(conn)
181+
setLoading('Logging in...')
171182
}
172-
} else if (isConnection(conn)) conn.connection.close() // No memory leaky
173-
})
174-
.catch(e => {
175-
console.error(e)
176-
closeChatScreen()
177-
setDisconnectReason({
178-
server: route.params.serverName,
179-
reason: 'An error occurred resolving the server hostname!'
180-
})
181-
})
183+
} else if (typeof conn !== 'string') conn.connection.close()
184+
}
185+
})().catch(err => {
186+
console.error(err)
187+
if (statusRef.current !== 'CLOSED') {
188+
const reason = 'An unknown error occurred!\n' + err
189+
closeChatScreen({ server: serverName, reason })
190+
}
191+
})
182192
}
183193
})
184194

@@ -190,7 +200,7 @@ const ChatScreen = ({ navigation, route }: Props) => {
190200
packetHandler(
191201
healthRef,
192202
statusRef,
193-
setLoggedIn,
203+
setLoading,
194204
connection.connection,
195205
addMessage,
196206
settings.joinMessage,
@@ -276,7 +286,7 @@ const ChatScreen = ({ navigation, route }: Props) => {
276286
onPress={() => navigation.push('Settings')}
277287
/>
278288
</View>
279-
{(!loggedIn || !connection) && (
289+
{(loading || !connection) && (
280290
<View style={styles.loadingScreen}>
281291
<ActivityIndicator
282292
color='#00aaff'
@@ -285,10 +295,12 @@ const ChatScreen = ({ navigation, route }: Props) => {
285295
default: 'large'
286296
})}
287297
/>
288-
<Text style={styles.loadingScreenText}>Connecting...</Text>
298+
<Text style={styles.loadingScreenText}>
299+
{loading || 'Connecting to server...'}
300+
</Text>
289301
</View>
290302
)}
291-
{loggedIn && connection && (
303+
{!loading && connection && (
292304
<>
293305
<ChatMessageListMemo
294306
messages={messages}

src/screens/chat/packetHandler.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const packetHandler =
4949
(
5050
healthRef: React.MutableRefObject<number | null>,
5151
statusRef: React.MutableRefObject<Status>,
52-
setLoggedIn: React.Dispatch<React.SetStateAction<boolean>>,
52+
setLoading: React.Dispatch<React.SetStateAction<string>>,
5353
connection: ServerConnection,
5454
addMessage: (text: MinecraftChat) => any,
5555
joinMessage: string,
@@ -60,7 +60,7 @@ export const packetHandler =
6060
) =>
6161
(packet: Packet) => {
6262
if (statusRef.current === 'CONNECTING' && connection.loggedIn) {
63-
setLoggedIn(true)
63+
setLoading('')
6464
statusRef.current = 'CONNECTED'
6565
if (sendJoinMessage) {
6666
connection

src/screens/chat/sessionBuilder.ts

+45-29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Accounts } from '../../context/accountsContext'
22
import { Connection, DisconnectReason } from '../../context/connectionContext'
3-
import { Sessions, SetSession } from '../../context/sessionStore'
3+
import { Session, Sessions, SetSession } from '../../context/sessionStore'
44
import { Servers } from '../../context/serversContext'
55
import { Settings } from '../../context/settingsContext'
66
import {
@@ -16,40 +16,32 @@ import initiateConnection from '../../minecraft/connection'
1616
import { parseIp, protocolMap, resolveHostname } from '../../minecraft/utils'
1717
import config from '../../../config.json'
1818

19-
export const createConnection = async (
20-
server: string,
19+
export const getSession = async (
2120
version: number,
22-
servers: Servers,
23-
settings: Settings,
2421
accounts: Accounts,
2522
sessions: Sessions,
2623
setSession: SetSession,
27-
setAccounts: (accs: Accounts) => void,
28-
setConnection: (conn?: Connection) => void,
29-
setDisconnectReason: (reason: DisconnectReason) => void,
30-
closeChatScreen: () => void
31-
): Promise<Connection | DisconnectReason> => {
32-
const [hostname, portNumber] = parseIp(servers[server].address)
33-
const [host, port] = await resolveHostname(hostname, portNumber)
24+
setLoading: (msg: string) => void,
25+
setAccounts: (accs: Accounts) => void
26+
): Promise<Session | string> => {
3427
const activeAccount = Object.keys(accounts).find(e => accounts[e].active)
3528
if (!activeAccount) {
36-
return {
37-
server,
38-
reason:
39-
'No active account selected! Open the Accounts tab and add an account.'
40-
}
29+
return 'No active account selected! Open the Accounts tab and add an account.'
4130
}
4231
const uuid = accounts[activeAccount].type ? activeAccount : undefined
32+
4333
// Create an updated "session" containing access tokens and certificates.
4434
let session = sessions[activeAccount]
4535
const is119 = version >= protocolMap[1.19]
46-
// TODO: We should store session store in a persistent cache. Certificates and access tokens should be updated regularly.
36+
// TODO: We should store session store in a persistent cache.
37+
// Certificates and access tokens should be updated regularly.
4738
if (uuid && (!session || (!session.certificate && is119))) {
4839
// We should probably lock access to them via a semaphore.
4940
try {
5041
// Create a session with the latest access token.
5142
const account = accounts[activeAccount]
5243
if (!session && accounts[activeAccount].type === 'microsoft') {
44+
setLoading('Reloading your Microsoft Account...')
5345
const [msAccessToken, msRefreshToken] = await refreshMSAuthToken(
5446
accounts[activeAccount].microsoftRefreshToken || '',
5547
config.clientId,
@@ -68,6 +60,7 @@ export const createConnection = async (
6860
}
6961
})
7062
} else if (!session && accounts[activeAccount].type === 'mojang') {
63+
setLoading('Reloading your Mojang Account...')
7164
const { accessToken, clientToken } = await refresh(
7265
accounts[activeAccount].accessToken || '',
7366
accounts[activeAccount].clientToken || '',
@@ -85,14 +78,37 @@ export const createConnection = async (
8578
}
8679
setSession(activeAccount, session)
8780
} catch (e) {
88-
const reason =
89-
'Failed to create session! You may need to re-login with your Microsoft Account in the Accounts tab.'
90-
return { server, reason }
81+
return 'Failed to create session! You may need to re-login with your Microsoft Account in the Accounts tab.'
9182
}
9283
}
84+
return session
85+
}
86+
87+
export const createConnection = async (
88+
server: string,
89+
version: number,
90+
servers: Servers,
91+
session: Session | undefined,
92+
settings: Settings,
93+
accounts: Accounts,
94+
setConnection: (conn?: Connection) => void,
95+
closeChatScreen: (reason?: DisconnectReason) => void
96+
): Promise<Connection | string> => {
97+
let host: string
98+
let port: number
99+
try {
100+
const [hostname, portNumber] = parseIp(servers[server].address)
101+
;[host, port] = await resolveHostname(hostname, portNumber)
102+
} catch (e) {
103+
return 'Failed to resolve server hostname!'
104+
}
105+
106+
const activeAccount = Object.keys(accounts).find(e => accounts[e].active)
107+
if (!activeAccount) {
108+
return 'No active account selected! Open the Accounts tab and add an account.'
109+
}
110+
const uuid = accounts[activeAccount].type ? activeAccount : undefined
93111

94-
// TODO: Better connection cancellation support. The session load can take a lot of time.
95-
// Connect to server after setting up the session.
96112
try {
97113
const newConn = await initiateConnection({
98114
host,
@@ -104,18 +120,18 @@ export const createConnection = async (
104120
certificate: settings.enableChatSigning ? session?.certificate : undefined
105121
})
106122
const onCloseOrError = () => {
107-
closeChatScreen()
123+
closeChatScreen(
124+
newConn.disconnectReason
125+
? { server, reason: parseValidJson(newConn.disconnectReason) }
126+
: undefined
127+
)
108128
setConnection(undefined)
109-
if (newConn.disconnectReason) {
110-
const reason = parseValidJson(newConn.disconnectReason)
111-
setDisconnectReason({ server, reason })
112-
}
113129
}
114130
newConn.on('close', onCloseOrError)
115131
newConn.on('error', onCloseOrError)
116132
return { serverName: server, connection: newConn }
117133
} catch (e) {
118134
console.error(e)
119-
return { server, reason: 'Failed to connect to server!' }
135+
return 'Failed to connect to server!'
120136
}
121137
}

0 commit comments

Comments
 (0)