网页视图

1import { Button, HStack, Image, List, Navigation, NavigationStack, Script, Section, Text, TextField, useMemo, useState, VStack, WebView } from "scripting"
2
3function WebViewControllerExample() {
4  const [logs, setLogs] = useState<{
5    content: string
6    error: boolean
7  }[]>([])
8
9  function addLog(content: string, error = false) {
10    setLogs(logs => [...logs, { content, error }])
11  }
12
13  async function runCode() {
14    setLogs([])
15    const controller = new WebViewController()
16
17    addLog("WebViewController created.")
18    addLog("Start loading...")
19
20    if (await controller.loadURL("https://github.com")) {
21      addLog("Website is loaded.")
22      addLog("Calling controller.evaluateJavaScript...")
23      const title = await controller.evaluateJavaScript<string>("document.title")
24
25      if (title != null) {
26        addLog(`Title: ${title}`)
27      } else {
28        addLog("Failed to get the title.", true)
29      }
30    } else {
31      addLog("Failed to load the website.", true)
32    }
33
34    controller.dispose()
35    addLog("The controller is disposed.")
36  }
37
38  return <Section
39    header={
40      <Text>WebView controller</Text>
41    }
42  >
43    <VStack
44      frame={{
45        maxWidth: "infinity"
46      }}
47      alignment={"leading"}
48    >
49      <Text font={"headline"}>This example will follow these steps:</Text>
50      <VStack
51        padding={{
52          leading: 16
53        }}
54        spacing={16}
55        foregroundStyle={"secondaryLabel"}
56        alignment={"leading"}
57      >
58        <Text>Create a WebViewController instane</Text>
59        <Text>Load https://github.com</Text>
60        <Text>Call evaluateJavaScript and get the title of the website</Text>
61      </VStack>
62      <HStack
63        alignment={"center"}
64        frame={{
65          maxWidth: "infinity"
66        }}
67      >
68        <Button
69          title={"Run"}
70          action={runCode}
71        />
72      </HStack>
73
74      <VStack
75        alignment={"leading"}
76        spacing={8}
77      >
78        {logs.map(log =>
79          <Text
80            font={"caption"}
81            monospaced
82            padding={{
83              leading: 16
84            }}
85            foregroundStyle={log.error ? "systemRed" : "systemGreen"}
86          >{log.content}</Text>
87        )}
88      </VStack>
89    </VStack>
90  </Section>
91}
92
93function PresentWebViewExample() {
94
95  function run() {
96    const controller = new WebViewController()
97    controller.loadURL("https://github.com")
98
99    controller.present({
100      fullscreen: true,
101      navigationTitle: "Github"
102    }).then(() => {
103      console.log("WebView is dismissed")
104      controller.dispose()
105    })
106  }
107
108  return <Section
109    header={
110      <Text>Present a WebView as a independent page</Text>
111    }
112  >
113    <Button
114      title={"Present"}
115      action={run}
116    />
117  </Section>
118}
119
120function EmbedAWebViewExample() {
121  const controller = useMemo(() => new WebViewController(), [])
122  const [url, setUrl] = useState("")
123
124  return <Section
125    header={
126      <Text>Embed a WebView</Text>
127    }
128  >
129    <VStack>
130      <HStack>
131        <Button action={() => {
132          controller.goBack()
133        }}>
134          <Image
135            systemName={"arrow.left"}
136          />
137        </Button>
138        <Button action={() => {
139          controller.goForward()
140        }}>
141          <Image
142            systemName={"arrow.right"}
143          />
144        </Button>
145        <Button action={() => {
146          controller.reload()
147        }}>
148          <Image
149            systemName={"arrow.clockwise"}
150          />
151        </Button>
152        <TextField
153          title={"Website URL"}
154          textFieldStyle={"roundedBorder"}
155          value={url}
156          onChanged={setUrl}
157          keyboardType={"URL"}
158          textInputAutocapitalization={"never"}
159          frame={{
160            maxWidth: "infinity"
161          }}
162        />
163        <Button
164          action={() => controller.loadURL(url)}
165        >
166          <Image
167            systemName={"arrow.right.circle"}
168          />
169        </Button>
170      </HStack>
171      <WebView
172        controller={controller}
173        frame={{
174          height: 400
175        }}
176      />
177    </VStack>
178  </Section>
179}
180
181function Example() {
182  return <NavigationStack>
183    <List
184      navigationTitle={"WebView"}
185      navigationBarTitleDisplayMode={"inline"}
186    >
187      <WebViewControllerExample />
188      <PresentWebViewExample />
189      <EmbedAWebViewExample />
190    </List>
191  </NavigationStack>
192}
193
194async function run() {
195  await Navigation.present({
196    element: <Example />
197  })
198
199  Script.exit()
200}
201
202run()