1/**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import wifi from '@ohos.wifi';
17import router from '@system.router';
18import deviceInfo from '@ohos.deviceInfo';
19import InputMethod from '@ohos.inputMethod';
20import WifiModel, { WifiScanInfo } from '../model/wifiImpl/WifiModel';
21import LogUtil from '../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
22import ConfigData from '../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
23import HeadComponent from '../../../../../../common/component/src/main/ets/default/headComponent';
24import ResourceUtil from '../../../../../../common/search/src/main/ets/default/common/ResourceUtil';
25import ImageAnimatorComponent from '../../../../../../common/component/src/main/ets/default/imageAnimatorComponent';
26
27const deviceTypeInfo = deviceInfo.deviceType;
28const miniPassWordSize = 8;
29const MODULE_TAG = ConfigData.TAG + 'WifiModel.WifiPasswd -> ';
30const DEFAULT_STROKE_WIDTH = '1vp';
31
32/**
33 * wifi password setting page
34 */
35@Entry
36@Component
37struct WifiPsd {
38  @State userInputs: string = '';
39  @State passwdHint: string = '';
40  @State tobeConnectedSSID: string = '';
41  @State isFocused: boolean = false;
42  @State @Watch("controlFailedDialog") ControlFailedDialog: boolean = false;
43  @State @Watch("connectingClosedDialog") ConnectingClosedDialog: boolean = false;
44  @StorageLink("wifiStatus")  @Watch("wifiStatusChange") wifiStatus: boolean = true;
45  private tobeConnectedAp: WifiScanInfo | null = null;
46  private isConnectedBefore: boolean = false;
47  private taskId: number = -1;
48  private toConnected: boolean = false;
49  private connectDialog: CustomDialogController | null = new CustomDialogController({
50    builder: connectProgressDialog({
51      ssid: this.tobeConnectedSSID,
52    }),
53    alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? DialogAlignment.Bottom : DialogAlignment.Center,
54    offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 }),
55    autoCancel: false,
56    customStyle: true
57  });
58  private failedDialog: CustomDialogController | null = new CustomDialogController({
59    builder: connectFailedDialog({ ControlFailedDialog: $ControlFailedDialog }),
60    alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? DialogAlignment.Bottom : DialogAlignment.Center,
61    offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 }),
62    autoCancel: true,
63    customStyle: true
64  });
65
66  private connectingAndClosedDialog: CustomDialogController = new CustomDialogController({
67    builder: connectingClosedDialog({ ConnectingClosedDialog: $ConnectingClosedDialog }),
68    alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? DialogAlignment.Bottom : DialogAlignment.Center,
69    offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 }),
70    autoCancel: true,
71    customStyle: true
72  });
73
74  controlFailedDialog() {
75    if (this.ControlFailedDialog) {
76      this.failedDialog?.close();
77      this.ControlFailedDialog = false;
78    }
79  }
80
81  connectingClosedDialog() {
82    if (this.ConnectingClosedDialog) {
83      this.connectingAndClosedDialog?.close();
84      this.ConnectingClosedDialog = false;
85      router.back({
86        uri: 'pages/wifi',
87      });
88    }
89  }
90
91  wifiStatusChange() {
92    if (!this.wifiStatus) {
93      this.connectDialog?.close();
94      this.connectingAndClosedDialog?.open();
95    }
96  }
97
98  build() {
99    Column() {
100      GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
101        Column() {
102          HeadComponent({
103            icBackIsVisibility: true,
104            headName: this.tobeConnectedSSID,
105            isActive: true
106          });
107
108          TextInput({ placeholder: this.passwdHint })
109            .type(InputType.Password)
110            .placeholderColor($r('sys.color.ohos_id_color_text_hint'))
111            .caretColor("red")
112            .placeholderFont({
113              size: $r("app.float.font_16"),
114              weight: FontWeight.Regular,
115              family: "sans-serif", style: FontStyle.Normal
116            })
117            .caretColor($r('sys.color.ohos_id_color_text_primary_activated'))
118            .backgroundColor($r('app.color.color_00000000_transparent'))
119            .height($r('app.float.wh_value_48'))
120            .borderRadius(0)
121            .margin({ top: $r('app.float.wh_value_8') })
122            .onFocus(() => {
123              LogUtil.info(MODULE_TAG + "text input is focused");
124              this.isFocused = true;
125            })
126            .onBlur(() => {
127              LogUtil.info(MODULE_TAG + "text input is moved");
128              this.isFocused = false;
129            })
130            .onChange((inputs: string) => {
131              this.userInputs = inputs;
132            })
133            .onSubmit((enterKey: EnterKeyType) => {
134              InputMethod.getInputMethodController().stopInput()
135                .then((ret) => {
136                  LogUtil.debug(`${ConfigData.TAG}, enterType: ${enterKey}, stopInput: ${ret}`);
137                })
138            });
139
140          Divider()
141            .color($r("sys.color.ohos_id_color_primary"))
142            .strokeWidth(DEFAULT_STROKE_WIDTH)
143            .opacity($r('sys.float.ohos_id_alpha_content_secondary'))
144            .padding({
145              left: $r('sys.float.ohos_id_default_padding_start'),
146              right: $r('sys.float.ohos_id_default_padding_end')
147            })
148
149          // Button
150          Flex({ justifyContent: FlexAlign.SpaceBetween }) {
151            Row() {
152              Button({ type: ButtonType.Capsule, stateEffect: true }) {
153                Text($r('app.string.cancel'))
154                  .fontSize($r('sys.float.ohos_id_text_size_body1'))
155                  .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
156                  .fontWeight(FontWeight.Medium)
157              }
158              .layoutWeight(ConfigData.LAYOUT_WEIGHT_1)
159              .height($r('app.float.wh_value_40'))
160              .backgroundColor($r('sys.color.ohos_id_color_button_normal'))
161              .onClick(() => {
162                router.back();
163              });
164
165              Column()
166                .width($r('app.float.distance_12'))
167                .height($r('app.float.application_button_height'))
168
169              Button({ type: ButtonType.Capsule, stateEffect: true }) {
170                Text($r('app.string.wifiButtonConnect'))
171                  .fontSize($r('sys.float.ohos_id_text_size_body1'))
172                  .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
173                  .fontWeight(FontWeight.Medium)
174              }
175              .layoutWeight(ConfigData.LAYOUT_WEIGHT_1)
176              .height($r('app.float.wh_value_40'))
177              .backgroundColor($r('sys.color.ohos_id_color_button_normal'))
178              .opacity(this.userInputs.length < miniPassWordSize ? $r('sys.float.ohos_fa_alpha_disabled') : 1)
179              .onClick(this.userInputs.length < miniPassWordSize ?
180                () => {
181                  LogUtil.info(MODULE_TAG + 'no text input in passwd page')
182                } :
183                () => {
184                  WifiModel.setUserSelectedAp(this.tobeConnectedAp);
185                  WifiModel.connectWiFi(this.userInputs);
186                  this.toConnected = true;
187                  this.connectDialog?.open();
188                });
189            }
190            .height(ConfigData.WH_100_100)
191            .padding(this.isFocused === false ? { bottom: $r("app.float.wh_padding_136") } : {
192              top: $r("app.float.wh_padding_212")
193            })
194            .alignItems(this.isFocused === false ? VerticalAlign.Bottom : VerticalAlign.Top)
195          }
196          .width(ConfigData.WH_100_100)
197        }
198        .useSizeType({
199          sm: { span: 4, offset: 0 },
200          md: { span: 6, offset: 1 },
201          lg: { span: 8, offset: 2 }
202        });
203      }
204      .width(ConfigData.WH_100_100)
205      .height(ConfigData.WH_100_100)
206    }
207    .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
208    .width(ConfigData.WH_100_100)
209    .height(ConfigData.WH_100_100);
210  }
211
212  aboutToAppear(): void {
213    LogUtil.info(MODULE_TAG + 'about to appear');
214    let params = router.getParams();
215    if (typeof params === 'undefined' || params === null) {
216      LogUtil.info(MODULE_TAG + 'pass invalid params from other page');
217      router.back({
218        uri: 'pages/wifi',
219      });
220    }
221    this.initTextInputHint();
222    this.tobeConnectedAp = params.apInfo as WifiScanInfo | null;
223    this.tobeConnectedSSID = this.tobeConnectedAp ? this.tobeConnectedAp.ssid : '';
224  }
225
226  onPageShow() {
227    LogUtil.info(MODULE_TAG + 'on page show');
228    this.isConnectedBefore = wifi.isConnected();
229
230    if (this.isConnectedBefore) {
231      LogUtil.info(MODULE_TAG + 'start task');
232      this.startLinkedInfoTask();
233    } else {
234      LogUtil.info(MODULE_TAG + 'start observer');
235      this.registerObserver();
236    }
237  }
238
239  onPageHide(): void {
240    LogUtil.info(MODULE_TAG + 'on page hide');
241    this.connectDialog?.close();
242    this.failedDialog?.close();
243
244    if (this.isConnectedBefore) {
245      this.clearLinkedInfoTask();
246    } else {
247      this.unregisterObserver();
248    }
249  }
250
251  aboutToDisappear(): void {
252    LogUtil.info(MODULE_TAG + 'about to disappear');
253  }
254
255  onBackPress() {
256    LogUtil.info('settings wifiPsd onBackPress');
257  }
258
259  initTextInputHint() {
260    ResourceUtil.getString($r("app.string.wifiPassword")).then(value => {
261      this.passwdHint = value;
262    });
263  }
264
265  registerObserver() {
266    LogUtil.info(MODULE_TAG + 'start to register observer');
267    WifiModel.registerWiFiConnectionObserver((code: Number) => {
268      LogUtil.info(MODULE_TAG + 'wifi connection code : ' + code);
269      // 0: disconnected, 1: connected
270      if (!this.toConnected) {
271        return;
272      }
273
274      if (code === 0) {
275        this.toConnected = false;
276        this.connectDialog?.close()
277        this.failedDialog?.open()
278        if (this.tobeConnectedAp) {
279          WifiModel.removeDeviceConfig(this.tobeConnectedAp);
280        }
281      }
282
283      if (code === 1) {
284        this.connectDialog?.close();
285        router.back({
286          uri: 'pages/wifi',
287        });
288      }
289      WifiModel.refreshApScanResults();
290    });
291  }
292
293  unregisterObserver() {
294    LogUtil.info(MODULE_TAG + 'start to unregister observer');
295    WifiModel.unregisterWiFiConnectionObserver();
296  }
297
298  startLinkedInfoTask() {
299    LogUtil.info(MODULE_TAG + 'start the get linked info task');
300    this.taskId = setInterval(() => {
301      wifi.getLinkedInfo((err, result) => {
302        if (err) {
303          LogUtil.info(MODULE_TAG + 'get linked info failed');
304          return;
305        }
306
307        // 1: Connecting, 4: Connected, 6: Disconnected
308        if (result.ssid === this.tobeConnectedSSID && result.connState === 4) {
309          this.connectDialog?.close();
310          router.back({
311            uri: 'pages/wifi',
312          });
313          WifiModel.refreshApScanResults();
314        }
315
316        if (result.connState === 6 && this.toConnected) {
317          this.toConnected = false;
318          this.connectDialog?.close();
319          this.failedDialog?.open();
320          if (this.tobeConnectedAp) {
321            WifiModel.removeDeviceConfig(this.tobeConnectedAp);
322          }
323          WifiModel.refreshApScanResults();
324        }
325      });
326    }, 2000);
327  }
328
329  clearLinkedInfoTask() {
330    if (this.taskId !== -1) {
331      LogUtil.info(MODULE_TAG + 'clear the get linked info task');
332      clearInterval(this.taskId);
333      this.taskId = -1;
334    }
335  }
336}
337
338@CustomDialog
339struct connectProgressDialog {
340  controller?: CustomDialogController;
341  @Prop ssid: string = '';
342  @State message: string = ''
343
344  aboutToAppear() {
345    ResourceUtil.getString($r('app.string.wifiTipsConnecting')).then((value) => {
346      this.message = value.replace('%s', this.ssid);
347    });
348  }
349
350  build() {
351    Column() {
352      Column() {
353        Row() {
354          Text(this.message)
355            .fontSize($r('sys.float.ohos_id_text_size_body1'))
356            .fontColor($r('sys.color.ohos_id_color_text_primary'))
357            .fontWeight(FontWeight.Regular)
358            .align(Alignment.Start)
359
360          Blank()
361
362          ImageAnimatorComponent({ imageWidth: $r('app.float.wh_value_24'),
363            imageHeight: $r('app.float.wh_value_24') })
364        }
365        .alignItems(VerticalAlign.Center)
366        .height($r("app.float.wh_value_48"))
367        .width($r(ConfigData.WH_100_100))
368        .margin($r("app.float.wh_value_24"))
369      }
370      .height($r("app.float.wh_value_96"))
371      .borderRadius($r("app.float.radius_32"))
372      .backgroundColor($r("app.color.white_bg_color"))
373    }
374    .width(deviceTypeInfo === 'phone' ? ConfigData.WH_100_100 : $r("app.float.wh_value_410"))
375    .padding(deviceTypeInfo === 'phone' ? { left: $r("app.float.wh_value_12"), right: $r("app.float.wh_value_12") } : {
376    })
377  }
378}
379
380@CustomDialog
381struct connectFailedDialog {
382  controller?: CustomDialogController;
383  @Link ControlFailedDialog: boolean;
384
385  build() {
386    Column() {
387      Column() {
388        Text($r("app.string.wifiTipsConnectAuthFailed"))
389          .fontSize($r('sys.float.ohos_id_text_size_body1'))
390          .fontColor($r('sys.color.ohos_id_color_text_primary'))
391          .fontWeight(FontWeight.Regular)
392          .margin({ top: $r("app.float.wh_value_24") })
393          .height($r("app.float.wh_value_21"))
394
395        Row() {
396          Text($r("app.string.wifiTipsGotIt"))
397            .fontSize($r('sys.float.ohos_id_text_size_body1'))
398            .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
399            .fontWeight(FontWeight.Medium)
400            .onClick(() => {
401              this.ControlFailedDialog = true;
402            })
403        }
404        .alignItems(VerticalAlign.Top)
405        .margin({ top: $r("app.float.wh_value_8") })
406        .padding({ top: $r("app.float.wh_value_9") })
407        .height($r("app.float.wh_value_56"))
408      }
409      .height($r("app.float.wh_value_109"))
410      .width(ConfigData.WH_100_100)
411      .borderRadius($r("app.float.radius_32"))
412      .alignItems(HorizontalAlign.Center)
413      .backgroundColor($r("app.color.white_bg_color"))
414    }
415    .width(deviceTypeInfo === 'phone' ? ConfigData.WH_100_100 : $r("app.float.wh_value_410"))
416    .padding(deviceTypeInfo === 'phone' ? { left: $r("app.float.wh_value_12"), right: $r("app.float.wh_value_12") } : {
417    })
418  }
419}
420
421@CustomDialog
422struct connectingClosedDialog {
423  controller?: CustomDialogController;
424  @Link ConnectingClosedDialog: boolean;
425
426  build() {
427    Column() {
428      Column() {
429        Text($r("app.string.wifiTipsConnectNetFailed"))
430          .fontSize($r('sys.float.ohos_id_text_size_body1'))
431          .fontColor($r('sys.color.ohos_id_color_text_primary'))
432          .fontWeight(FontWeight.Regular)
433          .margin({ top: $r("app.float.wh_value_24") })
434          .height($r("app.float.wh_value_21"))
435
436        Row() {
437          Text($r("app.string.wifiTipsGotIt"))
438            .fontSize($r('sys.float.ohos_id_text_size_body1'))
439            .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
440            .fontWeight(FontWeight.Medium)
441            .onClick(() => {
442              this.ConnectingClosedDialog = true;
443            })
444        }
445        .alignItems(VerticalAlign.Top)
446        .margin({ top: $r("app.float.wh_value_8") })
447        .padding({ top: $r("app.float.wh_value_9") })
448        .height($r("app.float.wh_value_56"))
449      }
450      .height($r("app.float.wh_value_109"))
451      .width(ConfigData.WH_100_100)
452      .borderRadius($r("app.float.radius_32"))
453      .alignItems(HorizontalAlign.Center)
454      .backgroundColor($r("app.color.white_bg_color"))
455    }
456    .width(deviceTypeInfo === 'phone' ? ConfigData.WH_100_100 : $r("app.float.wh_value_410"))
457    .padding(deviceTypeInfo === 'phone' ? { left: $r("app.float.wh_value_12"), right: $r("app.float.wh_value_12") } : {
458    })
459  }
460}
461