Integrated server emulation. Testing client...
+
+ {isRecording ? 'Recording packets...' : 'Integrated server emulation. Testing client...'}
+
+
@@ -228,4 +239,5 @@ export interface PacketData {
actualVersion?: any
position: number
timestamp: number
+ isCustomChannel?: boolean
}
diff --git a/src/react/Screen.tsx b/src/react/Screen.tsx
index a17ede40..605ec28f 100644
--- a/src/react/Screen.tsx
+++ b/src/react/Screen.tsx
@@ -6,14 +6,15 @@ interface Props {
className?: string
titleSelectable?: boolean
titleMarginTop?: number
+ contentStyle?: React.CSSProperties
}
-export default ({ title, children, backdrop = true, style, className = '', titleSelectable, titleMarginTop }: Props) => {
+export default ({ title, children, backdrop = true, style, className = '', titleSelectable, titleMarginTop, contentStyle }: Props) => {
return (
<>
{backdrop === 'dirt' ?
: backdrop ?
: null}
-
+
diff --git a/src/react/SelectOption.tsx b/src/react/SelectOption.tsx
index 4df471c0..c7b7ab38 100644
--- a/src/react/SelectOption.tsx
+++ b/src/react/SelectOption.tsx
@@ -48,21 +48,33 @@ export const showOptionsModal = async
(
})
}
-type InputOption = {
- type: 'text' | 'checkbox'
+export type InputOption = {
+ type: 'text' | 'checkbox' | 'button'
defaultValue?: string | boolean
label?: string
+ placeholder?: string
+ onButtonClick?: () => void
}
export const showInputsModal = async >(
title: string,
inputs: T,
- { cancel = true, minecraftJsonMessage }: { cancel?: boolean, minecraftJsonMessage? } = {}
+ {
+ cancel = true,
+ minecraftJsonMessage,
+ showConfirm = true
+ }: {
+ cancel?: boolean,
+ minecraftJsonMessage?
+ showConfirm?: boolean
+ } = {}
): Promise<{
[K in keyof T]: T[K] extends { type: 'text' }
? string
: T[K] extends { type: 'checkbox' }
? boolean
- : never
+ : T[K] extends { type: 'button' }
+ ? string
+ : never
}> => {
showModal({ reactType: 'general-select' })
let minecraftJsonMessageParsed
@@ -81,7 +93,7 @@ export const showInputsModal = async >(
showCancel: cancel,
minecraftJsonMessage: minecraftJsonMessageParsed,
options: [],
- inputsConfirmButton: 'Confirm'
+ inputsConfirmButton: showConfirm ? 'Confirm' : ''
})
})
}
@@ -130,6 +142,7 @@ export default () => {
autoFocus
type='text'
defaultValue={input.defaultValue as string}
+ placeholder={input.placeholder}
onChange={(e) => {
inputValues.current[key] = e.target.value
}}
@@ -148,6 +161,15 @@ export default () => {
{label}
)}
+ {input.type === 'button' && (
+
+ )}
})}
diff --git a/src/react/ServersListProvider.tsx b/src/react/ServersListProvider.tsx
index db1d7d77..cd44a27a 100644
--- a/src/react/ServersListProvider.tsx
+++ b/src/react/ServersListProvider.tsx
@@ -16,6 +16,11 @@ import { showOptionsModal } from './SelectOption'
import { useCopyKeybinding } from './simpleHooks'
import { AuthenticatedAccount, getInitialServersList, getServerConnectionHistory, setNewServersList } from './serversStorage'
import { appStorage, StoreServerItem } from './appStorageProvider'
+import Button from './Button'
+import { pixelartIcons } from './PixelartIcon'
+import { showNotification } from './NotificationProvider'
+
+const EXPLICIT_SHARE_SERVER_MODE = false
if (appQueryParams.lockConnect) {
notHideableModalsWithoutForce.add('editServer')
@@ -350,6 +355,27 @@ const Inner = ({ hidden, customServersList }: { hidden?: boolean, customServersL
}}
worldData={serversListSorted.map(server => {
const additional = additionalServerData[server.ip]
+ const handleShare = async () => {
+ try {
+ const qs = new URLSearchParams()
+ qs.set('ip', server.ip)
+ if (server.proxyOverride) qs.set('proxy', server.proxyOverride)
+ if (server.versionOverride) qs.set('version', server.versionOverride)
+ qs.set('username', server.usernameOverride ?? '')
+ const shareUrl = `${window.location.origin}${window.location.pathname}?${qs.toString()}`
+ await navigator.clipboard.writeText(shareUrl)
+ const MESSAGE = 'Server link copied to clipboard'
+ if (EXPLICIT_SHARE_SERVER_MODE) {
+ await showOptionsModal(MESSAGE, [])
+ } else {
+ showNotification(MESSAGE)
+ }
+ } catch (err) {
+ console.error(err)
+ showNotification('Failed to copy server link to clipboard')
+ }
+ }
+
return {
name: server.index.toString(),
title: server.name || server.ip,
@@ -359,6 +385,16 @@ const Inner = ({ hidden, customServersList }: { hidden?: boolean, customServersL
worldNameRightGrayed: additional?.textNameRightGrayed ?? '',
iconSrc: additional?.icon,
offline: additional?.offline,
+ afterTitleUi: (
+