1/*
2 * Copyright (c) 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 common from '@ohos.app.ability.common';
18
19let dmClass: deviceManager.DeviceManager | null;
20let TAG = '[DeviceManagerUI:ConfirmDialog]==>';
21const ACTION_ALLOW_AUTH_ONCE: number = 0;
22const ACTION_CANCEL_AUTH: number = 1;
23const ACTION_AUTH_CONFIRM_TIMEOUT: number = 2;
24const ACTION_ALLOW_AUTH_ALWAYS: number = 6;
25const MSG_CANCEL_CONFIRM_SHOW: number = 5;
26const DEVICE_TYPE_2IN1: number = 0xA2F;
27const DEVICE_TYPE_PC: number = 0x0C;
28const CAST_PKG_NAME: string = 'CastEngineService';
29
30@Entry
31@Component
32struct Index {
33  @State peerAppOperation: string = '';
34  @State peerCustomDescription: string = '';
35  @State peerDeviceName: string = '';
36  @State peerDeviceType: number = 0;
37  @State secondsNum: number = 30;
38  @State times: number = 0;
39  @State isAvailableType: boolean = false;
40  @State title: string = '';
41  @State isUserOperate: boolean = false;
42
43  initStatue() {
44    if (dmClass) {
45      console.log(TAG + 'deviceManager exist');
46      return;
47    }
48    deviceManager.createDeviceManager('com.ohos.devicemanagerui.confirm',
49      (err: Error, dm: deviceManager.DeviceManager) => {
50        if (err) {
51          console.log('createDeviceManager err:' + JSON.stringify(err) + ' --fail:' + JSON.stringify(dm));
52          return;
53        }
54        dmClass = dm;
55        dmClass.on('uiStateChange', (data: Record<string, string>) => {
56          console.log('uiStateChange executed, dialog closed' + JSON.stringify(data));
57          let tmpStr: Record<string, number> = JSON.parse(data.param);
58          let msg: number = tmpStr.uiStateMsg as number;
59          if (msg === MSG_CANCEL_CONFIRM_SHOW) {
60            this.destruction();
61            return;
62          }
63        });
64      });
65  }
66
67  getImages(peerdeviceType: number): Resource {
68    console.info('peerdeviceType is ' + peerdeviceType);
69    if (peerdeviceType === deviceManager.DeviceType.SPEAKER) {
70      this.isAvailableType = true;
71      return $r('sys.symbol.soundai_fill');
72    } else if (peerdeviceType === deviceManager.DeviceType.PHONE) {
73      this.isAvailableType = true;
74      return $r('sys.symbol.phone_fill_1');
75    } else if (peerdeviceType === deviceManager.DeviceType.TABLET) {
76      this.isAvailableType = true;
77      return $r('sys.symbol.pad_fill');
78    } else if (peerdeviceType === deviceManager.DeviceType.WEARABLE) {
79      this.isAvailableType = true;
80      return $r('sys.symbol.earphone_case_16896');
81    } else if (peerdeviceType === deviceManager.DeviceType.CAR) {
82      this.isAvailableType = true;
83      return $r('sys.symbol.car_fill');
84    } else if (peerdeviceType === deviceManager.DeviceType.TV) {
85      this.isAvailableType = true;
86      return $r('sys.symbol.smartscreen_fill');
87    } else if (peerdeviceType === DEVICE_TYPE_PC) {
88      this.isAvailableType = true;
89      return $r('sys.symbol.matebook_fill');
90    } else if (peerdeviceType === DEVICE_TYPE_2IN1) {
91      this.isAvailableType = true;
92      return $r('sys.symbol.matebook_fill');
93    } else {
94      this.isAvailableType = false;
95      return $r('sys.symbol.unknown_device_fill');
96    }
97  }
98
99  onPageShow() {
100    console.log('onPageShow');
101    this.initStatue();
102  }
103
104  onPageHide() {
105    console.log('onPageHide');
106    if (this.isUserOperate) {
107      console.log('user operate');
108      return;
109    }
110    this.onCancel();
111  }
112
113  destruction() {
114    if (dmClass != null) {
115      try {
116        dmClass.release();
117        dmClass = null;
118      } catch (error) {
119        console.log('dmClass release failed');
120      }
121    }
122    let session = AppStorage.get<UIExtensionContentSession>('ConfirmSession');
123    if (session) {
124      session.terminateSelf();
125    }
126  }
127
128  setUserOperation(operation: number) {
129    console.log(TAG + 'setUserOperation: ' + operation);
130    if (dmClass === null) {
131      console.log(TAG + 'setUserOperation: ' + 'dmClass null');
132      return;
133    }
134    try {
135      this.isUserOperate = true;
136      dmClass.setUserOperation(operation, 'extra');
137    } catch (error) {
138      console.log(TAG + 'dmClass setUserOperation failed');
139    }
140  }
141
142  aboutToAppear() {
143    console.log(TAG + 'aboutToAppear execute PinCustomDialog');
144    let context = getContext() as common.UIAbilityContext;
145
146    if (AppStorage.get('deviceName') != null) {
147      this.peerDeviceName = AppStorage.get('deviceName') as string;
148      console.log('peerDeviceName is ' + this.peerDeviceName);
149    }
150    let hostPkgLabel: string = AppStorage.get('hostPkgLabel') as string;
151    if (hostPkgLabel === CAST_PKG_NAME) {
152      this.title =
153        context.resourceManager.getStringSync($r('app.string.dm_confirm_title_cast').id, this.peerDeviceName);
154    } else if (hostPkgLabel != null) {
155      this.title = context.resourceManager.getStringSync($r('app.string.dm_confirm_title_hap').id, hostPkgLabel,
156        this.peerDeviceName);
157      this.peerCustomDescription = context.resourceManager.getStringSync($r('app.string.dm_confirm_intention').id);
158    } else {
159      let titleFirst: string =
160        context.resourceManager.getStringSync($r('app.string.dm_connect_device').id, this.peerDeviceName);
161      this.title =
162        context.resourceManager.getStringSync($r('app.string.dm_is_trust_device').id, titleFirst);
163      this.peerCustomDescription = context.resourceManager.getStringSync($r('app.string.dm_confirm_intention').id);
164    }
165
166    if (AppStorage.get('deviceType') != null) {
167      this.peerDeviceType = AppStorage.get('deviceType') as number;
168      console.log('peerDeviceType is ' + this.peerDeviceType);
169    }
170
171    this.times = setInterval(() => {
172      console.info('devicemanagerui confirm dialog run seconds:' + this.secondsNum);
173      this.secondsNum--;
174      if (this.secondsNum === 0) {
175        clearInterval(this.times);
176        this.times = 0;
177        this.setUserOperation(ACTION_AUTH_CONFIRM_TIMEOUT);
178        this.destruction();
179        console.info('click cancel times run out');
180      }
181    }, 1000);
182  }
183
184  onAllowOnce() {
185    console.log('allow once');
186    if (dmClass === null) {
187      console.log('createDeviceManager is null');
188      return;
189    }
190
191    console.log('allow once' + ACTION_ALLOW_AUTH_ONCE);
192    this.setUserOperation(ACTION_ALLOW_AUTH_ONCE);
193    this.destruction();
194  }
195
196  onAllowAlways() {
197    console.log('allow always');
198    if (dmClass === null) {
199      console.log('createDeviceManager is null');
200      return;
201    }
202
203    console.log('allow always' + ACTION_ALLOW_AUTH_ALWAYS);
204    this.setUserOperation(ACTION_ALLOW_AUTH_ALWAYS);
205    this.destruction();
206  }
207
208  onCancel() {
209    console.log('cancel');
210    if (dmClass === null) {
211      console.log('createDeviceManager is null');
212      return;
213    }
214
215    console.log('cancel' + ACTION_CANCEL_AUTH);
216    this.setUserOperation(ACTION_CANCEL_AUTH);
217    this.destruction();
218  }
219
220  @Builder
221  Symbol() {
222    Shape() {
223      Circle()
224        .width(52)
225        .height(52)
226        .fill($r('sys.color.ohos_id_color_activated'))
227      Column() {
228        SymbolGlyph(this.getImages(this.peerDeviceType))
229          .fontSize('36vp')
230          .renderingStrategy(SymbolRenderingStrategy.MULTIPLE_OPACITY)
231          .fontColor([$r('sys.color.ohos_id_color_primary_contrary')])
232          .offset({ x: 8, y: 8 })
233      }
234    }
235    .visibility(this.isAvailableType ? Visibility.Visible : Visibility.None)
236    .margin({ bottom: 12, top: 6 })
237  }
238
239  @Builder
240  Title() {
241    Column() {
242      Text(this.title)
243        .textAlign(TextAlign.Center)
244        .fontSize($r('sys.float.ohos_id_text_size_body2'))
245        .fontWeight(FontWeight.Regular)
246        .fontColor('#FFFFFF')
247        .width('auto')
248      Text(this.peerCustomDescription)
249        .textAlign(TextAlign.Center)
250        .fontColor('#99FFFFFF')
251        .fontWeight(FontWeight.Regular)
252        .fontSize($r('sys.float.ohos_id_text_size_body3'))
253        .width('auto')
254        .margin({ top: 2 })
255        .visibility(this.peerCustomDescription === '' ? Visibility.None : Visibility.Visible)
256    }.margin({
257      top: this.isAvailableType ? 0 : 6,
258      bottom: 12, left: 26, right: 26 })
259  }
260
261  @Builder
262  Buttons() {
263    Column() {
264      Button($r('app.string.dm_allow_always'))
265        .margin({ bottom: 12 })
266        .onClick(() => {
267          this.onAllowAlways();
268        })
269        .fontColor('#FFFFFF')
270        .fontSize($r('sys.float.ohos_id_text_size_button2'))
271        .height(40)
272        .width('100%')
273        .backgroundColor('#1F71FF')
274      Button($r('app.string.dm_allow_temp'))
275        .margin({ bottom: 12 })
276        .onClick(() => {
277          this.onAllowOnce();
278        })
279        .fontColor('#5EA1FF')
280        .fontSize($r('sys.float.ohos_id_text_size_button2'))
281        .height(40)
282        .width('100%')
283        .backgroundColor('#405ea1ff')
284      Button($r('app.plural.dm_not_allow', this.secondsNum, this.secondsNum))
285        .onClick(() => {
286          this.onCancel();
287        })
288        .fontColor('#5EA1FF')
289        .fontSize($r('sys.float.ohos_id_text_size_button2'))
290        .height(40)
291        .width('100%')
292        .backgroundColor('#405ea1ff')
293    }
294    .margin({ left: 50, right: 50, bottom: 36})
295  }
296
297  build() {
298    Scroll() {
299      Column() {
300        this.Symbol();
301        this.Title();
302        this.Buttons();
303      }
304    }
305    .backgroundColor(Color.Black)
306    .height('100%')
307   .width('100%')
308  }
309}
310