• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2024 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 */
15import deviceManager from '@ohos.distributedHardware.deviceManager';
16import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
17import deviceInfo from '@ohos.deviceInfo';
18import Constant from '../common/constant';
19import common from '@ohos.app.ability.common';
20import display from '@ohos.display';
21import mediaQuery from '@ohos.mediaquery';
22import i18n from '@ohos.i18n';
23import { KeyCode } from '@ohos.multimodalInput.keyCode';
24
25let dmClass: deviceManager.DeviceManager | null;
26let TAG = '[DeviceManagerUI:ConfirmDialog]==>';
27const ACTION_ALLOW_AUTH_ONCE: number = 0;
28const ACTION_CANCEL_AUTH: number = 1;
29const ACTION_AUTH_CONFIRM_TIMEOUT: number = 2;
30const ACTION_ALLOW_AUTH_ALWAYS: number = 6;
31const MSG_CANCEL_CONFIRM_SHOW: number = 5;
32const DEVICE_TYPE_2IN1: number = 0xA2F;
33const DEVICE_TYPE_PC: number = 0x0C;
34const CAST_PKG_NAME: string = 'CastEngineService';
35
36@CustomDialog
37struct ConfirmCustomDialog {
38  @State peerAppOperation: string = '';
39  @State peerCustomDescription: string = '';
40  @State peerDeviceName: string = '';
41  @State peerDeviceType: number = 0;
42  @State secondsNum: number = 30;
43  @State times: number = 0;
44  @State isAvailableType: boolean = false;
45  @State btnColor: ResourceColor = Color.Transparent;
46  @State title: string = '';
47  controller?: CustomDialogController;
48  isPC: boolean = false;
49
50  aboutToAppear() {
51    console.log(TAG + 'aboutToAppear execute PinCustomDialog')
52    let context = getContext() as common.UIAbilityContext;
53
54    if (AppStorage.get('deviceName') != null) {
55      this.peerDeviceName = AppStorage.get('deviceName') as string;
56      console.log('peerDeviceName is ' + this.peerDeviceName);
57    }
58    let customDescriptionStr: string = AppStorage.get('customDescriptionStr') as string;
59    let hostPkgLabel: string = AppStorage.get('hostPkgLabel') as string;
60    if (hostPkgLabel === CAST_PKG_NAME) {
61      this.title =
62        context.resourceManager.getStringSync($r('app.string.dm_confirm_title_cast').id, this.peerDeviceName);
63    } else if (hostPkgLabel != null) {
64      this.title = context.resourceManager.getStringSync($r('app.string.dm_confirm_title_hap').id, hostPkgLabel,
65        this.peerDeviceName);
66      this.peerCustomDescription = context.resourceManager.getStringSync($r('app.string.dm_confirm_intention').id);
67      if (customDescriptionStr != undefined && customDescriptionStr != '') {
68        this.peerCustomDescription = this.peerDeviceName + customDescriptionStr;
69      }
70    } else {
71      let titleFirst: string =
72        context.resourceManager.getStringSync($r('app.string.dm_connect_device').id, this.peerDeviceName);
73      this.title =
74        context.resourceManager.getStringSync($r('app.string.dm_is_trust_device').id, titleFirst);
75      this.peerCustomDescription = context.resourceManager.getStringSync($r('app.string.dm_confirm_intention').id);
76    }
77
78    if (AppStorage.get('deviceType') != null) {
79      this.peerDeviceType = AppStorage.get('deviceType') as number;
80      console.log('peerDeviceType is ' + this.peerDeviceType);
81    }
82
83    this.times = setInterval(() => {
84      console.info('devicemanagerui confirm dialog run seconds:' + this.secondsNum);
85      this.secondsNum--;
86      if (this.secondsNum === 0) {
87        clearInterval(this.times);
88        this.times = 0;
89        this.setUserOperation(ACTION_AUTH_CONFIRM_TIMEOUT);
90        this.destruction();
91        console.info('click cancel times run out');
92      }
93    }, 1000)
94    console.log(TAG + 'deviceInfo.deviceType:' + deviceInfo.deviceType);
95    this.isPC = Constant.isPC();
96  }
97
98  onAllowOnce() {
99    console.log('allow once')
100    if (dmClass == null) {
101      console.log('createDeviceManager is null')
102      return
103    }
104
105    console.log('allow once' + ACTION_ALLOW_AUTH_ONCE)
106    this.setUserOperation(ACTION_ALLOW_AUTH_ONCE)
107    this.destruction()
108  }
109
110  onAllowAlways() {
111    console.log('allow always')
112    if (dmClass == null) {
113      console.log('createDeviceManager is null')
114      return
115    }
116
117    console.log('allow always' + ACTION_ALLOW_AUTH_ALWAYS)
118    this.setUserOperation(ACTION_ALLOW_AUTH_ALWAYS)
119    this.destruction()
120  }
121
122  onCancel() {
123    console.log('cancel')
124    if (dmClass == null) {
125      console.log('createDeviceManager is null')
126      return
127    }
128
129    console.log('cancel' + ACTION_CANCEL_AUTH)
130    this.setUserOperation(ACTION_CANCEL_AUTH)
131    this.destruction()
132  }
133
134  setUserOperation(operation: number) {
135    console.log(TAG + 'setUserOperation: ' + operation)
136    if (dmClass == null) {
137      console.log(TAG + 'setUserOperation: ' + 'dmClass null')
138      return;
139    }
140    try {
141      dmClass.setUserOperation(operation, 'extra');
142    } catch (error) {
143      console.log(TAG + 'dmClass setUserOperation failed')
144    }
145  }
146
147  destruction() {
148    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
149    if (session) {
150      session.terminateSelf();
151    }
152  }
153
154  getImages(peerdeviceType: number): Resource {
155    console.info('peerdeviceType is ' + peerdeviceType);
156    if (peerdeviceType === deviceManager.DeviceType.SPEAKER) {
157      this.isAvailableType = true;
158      return $r('sys.symbol.soundai_fill');
159    } else if (peerdeviceType === deviceManager.DeviceType.PHONE) {
160      this.isAvailableType = true;
161      return $r('sys.symbol.phone_fill_1');
162    } else if (peerdeviceType === deviceManager.DeviceType.TABLET) {
163      this.isAvailableType = true;
164      return $r('sys.symbol.pad_fill');
165    } else if (peerdeviceType === deviceManager.DeviceType.WEARABLE) {
166      this.isAvailableType = true;
167      return $r('sys.symbol.earphone_case_16896');
168    } else if (peerdeviceType === deviceManager.DeviceType.CAR) {
169      this.isAvailableType = true;
170      return $r('sys.symbol.car_fill');
171    } else if (peerdeviceType === deviceManager.DeviceType.TV) {
172      this.isAvailableType = true;
173      return $r('sys.symbol.smartscreen_fill');
174    } else if (peerdeviceType === DEVICE_TYPE_PC) {
175      this.isAvailableType = true;
176      return $r('sys.symbol.matebook_fill');
177    } else if (peerdeviceType === DEVICE_TYPE_2IN1) {
178      this.isAvailableType = true;
179      return $r('sys.symbol.matebook_fill');
180    } else {
181      this.isAvailableType = false;
182      return $r('sys.symbol.unknown_device_fill');
183    }
184  }
185
186  @Builder
187  Symbol() {
188    Shape() {
189      Circle()
190        .width(32)
191        .height(32)
192        .fill($r('sys.color.ohos_id_color_activated'))
193      Column() {
194        SymbolGlyph(this.getImages(this.peerDeviceType))
195          .fontSize('20vp')
196          .renderingStrategy(SymbolRenderingStrategy.MULTIPLE_OPACITY)
197          .fontColor([$r('sys.color.ohos_id_color_primary_contrary')])
198          .offset({ x: 6, y: 6 })
199      }
200    }
201    .visibility(this.isAvailableType ? Visibility.Visible : Visibility.None)
202    .margin({ bottom: 16, top: 24 })
203  }
204
205  private isTibetanLanguages(): boolean {
206    console.info(`${TAG} isTibetanLanguages in`);
207    let locale = new Intl.Locale(i18n.System.getSystemLanguage()).toString();
208    console.info(`${TAG} isTibetanLanguages: ${locale}`);
209    return Constant.TIBETAN_LANGUAGES.includes(locale);
210  }
211
212  build() {
213    GridRow({
214      columns: { xs: 4, sm: 8, md: this.isPC ? 24 : 12 },
215      gutter: { x: 4 },
216      breakpoints: { value: ['600vp', '840vp'] }
217    }) {
218      GridCol({ span: { xs: 4, sm: 4, md: this.isPC ? 6 : 4 }, offset: { sm: 2, md: this.isPC ? 9 : 4 } }) {
219        Column() {
220          this.Symbol();
221          Column() {
222            Text(this.title)
223              .textAlign(TextAlign.Center)
224              .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle'))
225              .fontWeight(FontWeight.Bold)
226              .fontColor($r('sys.color.ohos_id_color_text_primary'))
227              .minFontSize(12)
228              .maxFontSize($r('sys.float.ohos_id_text_size_dialog_tittle'))
229              .heightAdaptivePolicy(TextHeightAdaptivePolicy.LAYOUT_CONSTRAINT_FIRST)
230              .lineHeight(this.isTibetanLanguages() ? 22 : 0)
231              .textOverflow({ overflow: TextOverflow.Ellipsis })
232              .width('auto')
233              .maxLines(2)
234            Text(this.peerCustomDescription)
235              .textAlign(TextAlign.Start)
236              .fontColor($r('sys.color.ohos_id_color_text_secondary'))
237              .fontWeight(FontWeight.Regular)
238              .textOverflow({ overflow: TextOverflow.Ellipsis })
239              .fontSize($r('sys.float.ohos_id_text_size_body2'))
240              .maxLines(2)
241              .width('auto')
242              .lineHeight(this.isTibetanLanguages() ? 22 : 0)
243              .margin({ top: 8 })
244              .visibility(this.peerCustomDescription === '' ? Visibility.None : Visibility.Visible)
245          }.margin({
246            top: this.isAvailableType ? 0 : 24,
247            bottom: 16, left: 24, right: 24 })
248
249          Column() {
250            Button($r('app.string.dm_allow_always'))
251              .margin({ bottom: 4 })
252              .onClick(() => {
253                this.onAllowAlways();
254              })
255              .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
256              .height(this.isTibetanLanguages() ? 'auto' : 40)
257              .width(this.isPC ? 250 : '100%')
258              .backgroundColor(this.btnColor)
259              .onHover((isHover?: boolean, event?: HoverEvent): void => {
260                if (isHover) {
261                  this.btnColor = $r('sys.color.ohos_id_color_hover');
262                } else {
263                  this.btnColor = this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent;
264                }
265              })
266              .stateStyles({
267                pressed: {
268                  .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
269                },
270                normal: {
271                  .backgroundColor(this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent)
272                }
273              })
274            Button($r('app.string.dm_allow_temp'))
275              .margin({ bottom: 4 })
276              .onClick(() => {
277                this.onAllowOnce();
278              })
279              .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
280              .height(this.isTibetanLanguages() ? 'auto' : 40)
281              .width(this.isPC ? 250 : '100%')
282              .backgroundColor(this.btnColor)
283              .onHover((isHover?: boolean, event?: HoverEvent): void => {
284                if (isHover) {
285                  this.btnColor = $r('sys.color.ohos_id_color_hover');
286                } else {
287                  this.btnColor = this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent;
288                }
289              })
290              .stateStyles({
291                pressed: {
292                  .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
293                },
294                normal: {
295                  .backgroundColor(this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent)
296                }
297              })
298            Button($r('app.plural.dm_not_allow', this.secondsNum, this.secondsNum))
299              .margin({ left: 16, right: 16 })
300              .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
301              .defaultFocus(true)
302              .onKeyEvent((event?: KeyEvent) => {
303                if (event && event?.keyCode === KeyCode.KEYCODE_HOME && event?.type === KeyType.Down) {
304                  console.log(TAG + 'onKeyEvent eventType: ' + event?.type)
305                  return;
306                }
307                if (event && event?.keyCode === KeyCode.KEYCODE_HOME && event?.type === KeyType.Up) {
308                  console.log(TAG + 'onKeyEvent eventType: ' + event?.type)
309                  this.onCancel();
310                }
311              })
312              .onClick(() => {
313                this.onCancel();
314              })
315              .height(this.isTibetanLanguages() ? 'auto' : 40)
316              .width(this.isPC ? 250 : '100%')
317              .backgroundColor(this.btnColor)
318              .onHover((isHover?: boolean, event?: HoverEvent): void => {
319                if (isHover) {
320                  this.btnColor = $r('sys.color.ohos_id_color_hover');
321                } else {
322                  this.btnColor = this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent;
323                }
324              })
325              .stateStyles({
326                pressed: {
327                  .backgroundColor($r('sys.color.ohos_id_color_click_effect'))
328                },
329                normal: {
330                  .backgroundColor(this.isPC ? $r('sys.color.ohos_id_color_button_normal') : Color.Transparent)
331                }
332              })
333          }
334          .margin({
335            left: 16,
336            right: 16,
337            bottom: this.isPC ? 24 : 8
338          })
339        }
340        .borderRadius($r('sys.float.ohos_id_corner_radius_dialog'))
341        .backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK)
342        .margin({ left: $r('sys.float.ohos_id_dialog_margin_start'), right: $r('sys.float.ohos_id_dialog_margin_end') })
343      }
344    }.constraintSize({ maxHeight: '90%' })
345  }
346}
347
348@Entry
349@Component
350struct dialogPlusPage {
351  dialogController: CustomDialogController = new CustomDialogController({
352    builder: ConfirmCustomDialog(),
353    autoCancel: false,
354    onWillDismiss: ()=>{
355      this.onWillDismiss()
356    },
357    alignment: DialogAlignment.Center,
358    offset: { dx: 0, dy: -20 },
359    customStyle: true,
360    maskColor: $r('sys.color.ohos_id_color_mask_thin')
361  });
362
363  initStatue() {
364    if (dmClass) {
365      console.log(TAG + 'deviceManager exist')
366      return
367    }
368    deviceManager.createDeviceManager('com.ohos.devicemanagerui.confirm',
369      (err: Error, dm: deviceManager.DeviceManager) => {
370        if (err) {
371          console.log('createDeviceManager err:' + JSON.stringify(err) + ' --fail:' + JSON.stringify(dm))
372          return
373        }
374        dmClass = dm
375        dmClass.on('uiStateChange', (data: Record<string, string>) => {
376          console.log('uiStateChange executed, dialog closed' + JSON.stringify(data))
377          let tmpStr: Record<string, number> = JSON.parse(data.param)
378          let msg: number = tmpStr.uiStateMsg as number
379          if (msg === MSG_CANCEL_CONFIRM_SHOW) {
380            console.log('cancel confirm show.')
381            this.destruction()
382            return
383          }
384        })
385      })
386  }
387
388  onWillDismiss() {
389    console.log(TAG + 'onWillDismiss: ' + ACTION_CANCEL_AUTH)
390    this.setUserOperation(ACTION_CANCEL_AUTH);
391    this.destruction();
392  }
393
394  setUserOperation(operation: number) {
395    console.log(TAG + 'setUserOperation: ' + operation)
396    if (dmClass == null) {
397      console.log(TAG + 'setUserOperation: ' + 'dmClass null')
398      return;
399    }
400    try {
401      dmClass.setUserOperation(operation, 'extra');
402    } catch (error) {
403      console.log(TAG + 'dmClass setUserOperation failed')
404    }
405  }
406
407  onPageShow() {
408    console.log('onPageShow')
409    this.initStatue()
410  }
411
412  destruction() {
413    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
414    if (session) {
415      session.terminateSelf();
416    }
417  }
418
419  aboutToDisappear() {
420    console.log(TAG + 'aboutToDisappear aboutToDisappear')
421    if (dmClass != null) {
422      try {
423        dmClass.off('uiStateChange');
424        dmClass.release();
425      } catch (error) {
426        console.log('dmClass release failed')
427      }
428      dmClass = null
429    }
430  }
431
432  build() {
433    Column(this.dialogController.open())
434  }
435}