tcpip.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // cspell: ignore addrs
  2. import { ICommandBarItemProps, MessageBar, Stack, StackItem, Text, TextField, Toggle } from "@fluentui/react";
  3. import { autorun, makeAutoObservable, runInAction } from "mobx";
  4. import { observer } from "mobx-react-lite";
  5. import { NextPage } from "next";
  6. import Head from "next/head";
  7. import { useCallback, useEffect } from "react";
  8. import { CommandBar, ExternalLink } from "../components";
  9. import { GlobalState } from "../state";
  10. import { asyncEffect, Icons, RouteStackProps } from "../utils";
  11. class TcpIpState {
  12. initial = true;
  13. visible = false;
  14. serviceListenAddresses: string[] | undefined = undefined;
  15. servicePortEnabled = false;
  16. servicePort: string = '';
  17. persistPortEnabled = false;
  18. persistPort: string | undefined = undefined;
  19. constructor() {
  20. makeAutoObservable(this, {
  21. initial: false,
  22. queryInfo: false,
  23. applyServicePort: false,
  24. });
  25. autorun(() => {
  26. if (GlobalState.device) {
  27. if (this.initial && this.visible) {
  28. this.initial = false;
  29. this.queryInfo();
  30. }
  31. } else {
  32. this.initial = true;
  33. }
  34. });
  35. }
  36. get commandBarItems(): ICommandBarItemProps[] {
  37. return [
  38. {
  39. key: 'refresh',
  40. disabled: !GlobalState.device,
  41. iconProps: { iconName: Icons.ArrowClockwise },
  42. text: 'Refresh',
  43. onClick: this.queryInfo as VoidFunction,
  44. },
  45. {
  46. key: 'apply',
  47. disabled: !GlobalState.device,
  48. iconProps: { iconName: Icons.Save },
  49. text: 'Apply',
  50. onClick: this.applyServicePort,
  51. }
  52. ];
  53. }
  54. queryInfo = asyncEffect(async (signal) => {
  55. if (!GlobalState.device) {
  56. runInAction(() => {
  57. this.serviceListenAddresses = undefined;
  58. this.servicePortEnabled = false;
  59. this.servicePort = '';
  60. this.persistPortEnabled = false;
  61. this.persistPort = undefined;
  62. });
  63. return;
  64. }
  65. const serviceListenAddresses = await GlobalState.device.getProp('service.adb.listen_addrs');
  66. const servicePort = await GlobalState.device.getProp('service.adb.tcp.port');
  67. const persistPort = await GlobalState.device.getProp('persist.adb.tcp.port');
  68. if (signal.aborted) {
  69. return;
  70. }
  71. runInAction(() => {
  72. this.serviceListenAddresses = serviceListenAddresses !== '' ? serviceListenAddresses.split(',') : undefined;
  73. if (servicePort) {
  74. this.servicePortEnabled = !serviceListenAddresses && servicePort !== '0';
  75. this.servicePort = servicePort;
  76. } else {
  77. this.servicePortEnabled = false;
  78. this.servicePort = '5555';
  79. }
  80. if (persistPort) {
  81. this.persistPortEnabled = !serviceListenAddresses && !servicePort;
  82. this.persistPort = persistPort;
  83. } else {
  84. this.persistPortEnabled = false;
  85. this.persistPort = undefined;
  86. }
  87. });
  88. });
  89. applyServicePort = async () => {
  90. if (!GlobalState.device) {
  91. return;
  92. }
  93. if (state.servicePortEnabled) {
  94. await GlobalState.device.tcpip.setPort(Number.parseInt(state.servicePort, 10));
  95. } else {
  96. await GlobalState.device.tcpip.disable();
  97. }
  98. };
  99. }
  100. const state = new TcpIpState();
  101. const TcpIp: NextPage = () => {
  102. useEffect(() => {
  103. runInAction(() => {
  104. state.visible = true;
  105. });
  106. return () => {
  107. runInAction(() => {
  108. state.visible = false;
  109. });
  110. };
  111. });
  112. const handleServicePortEnabledChange = useCallback((e: unknown, value?: boolean) => {
  113. runInAction(() => { state.servicePortEnabled = !!value; });
  114. }, []);
  115. const handleServicePortChange = useCallback((e: unknown, value?: string) => {
  116. if (value === undefined) {
  117. return;
  118. }
  119. runInAction(() => state.servicePort = value);
  120. }, []);
  121. return (
  122. <Stack {...RouteStackProps}>
  123. <Head>
  124. <title>ADB over WiFi - Android Web Toolbox</title>
  125. </Head>
  126. <CommandBar items={state.commandBarItems} />
  127. <StackItem>
  128. <MessageBar>
  129. <Text>
  130. For WebADB to wirelessly connect to your device,
  131. <ExternalLink href="https://github.com/yume-chan/ya-webadb/discussions/245#discussioncomment-384030" spaceBefore spaceAfter>extra software</ExternalLink>
  132. is required.
  133. </Text>
  134. </MessageBar>
  135. </StackItem>
  136. <StackItem>
  137. <MessageBar >
  138. <Text>Your device will disconnect after changing ADB over WiFi config.</Text>
  139. </MessageBar>
  140. </StackItem>
  141. <StackItem>
  142. <Toggle
  143. inlineLabel
  144. label="service.adb.listen_addrs"
  145. disabled
  146. checked={!!state.serviceListenAddresses}
  147. onText="Enabled"
  148. offText="Disabled"
  149. />
  150. {state.serviceListenAddresses?.map((address) => (
  151. <TextField
  152. key={address}
  153. disabled
  154. value={address}
  155. styles={{ root: { width: 300 } }}
  156. />
  157. ))}
  158. </StackItem>
  159. <StackItem>
  160. <Toggle
  161. inlineLabel
  162. label="service.adb.tcp.port"
  163. checked={state.servicePortEnabled}
  164. disabled={!GlobalState.device || !!state.serviceListenAddresses}
  165. onText="Enabled"
  166. offText="Disabled"
  167. onChange={handleServicePortEnabledChange}
  168. />
  169. <TextField
  170. disabled={!GlobalState.device || !!state.serviceListenAddresses}
  171. value={state.servicePort}
  172. styles={{ root: { width: 300 } }}
  173. onChange={handleServicePortChange}
  174. />
  175. </StackItem>
  176. <StackItem>
  177. <Toggle
  178. inlineLabel
  179. label="persist.adb.tcp.port"
  180. disabled
  181. checked={state.persistPortEnabled}
  182. onText="Enabled"
  183. offText="Disabled"
  184. />
  185. {state.persistPort && (
  186. <TextField
  187. disabled
  188. value={state.persistPort}
  189. styles={{ root: { width: 300 } }}
  190. />
  191. )}
  192. </StackItem>
  193. </Stack>
  194. );
  195. };
  196. export default observer(TcpIp);