1/** 2 * Copyright (c) 2023-2023 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 { 17 AppMenu, 18 FormManagerDialog, 19} from '@ohos/common/component' 20import { 21 CommonConstants, 22 StyleConstants, 23 LayoutViewModel, 24 CardItemInfo, 25 FormModel, 26 Log, 27 SettingsModel, 28 windowManager, 29 AppItemInfo, 30 ResourceManager, 31 MenuInfo, 32 AppModel, 33 localEventManager, 34 EventConstants 35} from '@ohos/common'; 36import ServiceFormAppItem from '../common/uicomponents/ServiceFormAppItem'; 37import ServiceFormItem from '../common/uicomponents/ServiceFormItem'; 38import ThisStyleConstants from '../common/constants/StyleConstants'; 39import GridRowUtils from '../manager/GridRowManager'; 40import ServiceFormManager from '../manager/ServiceFormManager'; 41import { PageDesktopViewModel } from '../../../../../../pagedesktop/src/main/ets/default/viewmodel/PageDesktopViewModel'; 42 43const TAG = 'FormServiceComponent'; 44 45/** 46 * Form service view Component (phone adaptation). 47 */ 48@Component 49export struct FormServiceComponent { 50 @StorageLink('screenWidth') @Watch('initPage') screenWidth: number = 0; 51 @StorageLink('screenHeight') screenHeight: number = 0; 52 @State formAppInfos: AppItemInfo[] = []; 53 @State showFormInfos: CardItemInfo[] = new Array(); 54 private readonly mServiceFormManager: ServiceFormManager = ServiceFormManager.getInstance(); 55 private mFormModel: FormModel = FormModel.getInstance(); 56 private mAppModel: AppModel = AppModel.getInstance(); 57 private clickedformApp: AppItemInfo = new AppItemInfo(); 58 private clearForm: Function = () => {}; 59 private gridRowUtils: GridRowUtils = new GridRowUtils(0, 0, 0); 60 private formServiceWidth: number = 0; 61 private titleBarWidth: number = 0; 62 private sysUITopHeight: number = 0; 63 private sysUIBottomHeight: number = 0; 64 private scrollerWrapHeight: number = 0; 65 private scroller: Scroller = new Scroller(); 66 @StorageProp('cornerRadiusDefaultL') cornerRadiusDefaultL: number = px2vp(ResourceManager.getInstance() 67 .getNumberByResource($r('sys.float.ohos_id_corner_radius_default_l'))); 68 69 private async initServiceFormInfo(): Promise<void> { 70 // 从包管理获取app 71 this.formAppInfos = await this.mServiceFormManager.getServiceFormAppList(); 72 Log.showInfo(TAG, `has ${this.formAppInfos.length} apps with form`); 73 74 // 获取推荐卡片 75 let recommendForms: CardItemInfo[] = await this.mServiceFormManager.getServiceForm(); 76 Log.showInfo(TAG, `recommendCardsDataPool has ${recommendForms.length} cards`); 77 // 卡片信息补全 78 this.mServiceFormManager.formInfoComplete(recommendForms, this.formAppInfos); 79 // 获取展示卡片 80 this.showFormInfos = this.mServiceFormManager.getShowFormInfos(recommendForms); 81 Log.showInfo(TAG, `this.showFormInfos has ${this.showFormInfos.length} cards`); 82 } 83 84 private onAppStateChanged = () => { 85 // 推荐卡片更新后需要重新获取推荐列表 86 this.initServiceFormInfo(); 87 } 88 private readonly listener = this.onAppStateChanged; 89 90 /** 91 * 返回箭头 92 */ 93 private backToDeskTop(): void { 94 windowManager.destroyWindow(windowManager.FORM_SERVICE_WINDOW_NAME); 95 } 96 97 aboutToAppear(): void { 98 this.sysUITopHeight = LayoutViewModel.getInstance().getSysUITopHeight(); 99 this.sysUIBottomHeight = LayoutViewModel.getInstance().getSysUIBottomHeight(); 100 Log.showDebug(TAG, `sysUITopHeight:${this.sysUITopHeight},sysUIBottomHeight:${this.sysUIBottomHeight}`); 101 this.scrollerWrapHeight = this.screenHeight - ThisStyleConstants.FORM_SERVICE_BAR_HEIGHT - this.sysUITopHeight 102 - this.sysUIBottomHeight; 103 this.initPage(); 104 this.mAppModel.registerStateChangeListener(this.listener); 105 this.onAppStateChanged(); 106 } 107 108 aboutToDisappear(): void { 109 this.formManagerDialogController = null; 110 this.mAppModel.unregisterAppStateChangeListener(this.listener); 111 } 112 113 initPage(): void { 114 this.titleBarWidth = this.screenWidth - 2 * ThisStyleConstants.FORM_SERVICE_MARGIN_HORIZONTAL; 115 if (this.screenWidth < 520) { 116 this.formServiceWidth = this.titleBarWidth; 117 this.gridRowUtils = new GridRowUtils(ThisStyleConstants.FORM_SERVICE_GRID_ROW_COLUMNS, 118 ThisStyleConstants.FORM_SERVICE_GRID_ROW_GUTTER_X, this.formServiceWidth); 119 } else if (this.screenWidth < 840) { 120 let gridRowUtilsTemp: GridRowUtils = new GridRowUtils(ThisStyleConstants.FORM_SERVICE_GRID_ROW_COLUMNS * 2, 121 ThisStyleConstants.FORM_SERVICE_GRID_ROW_GUTTER_X, this.titleBarWidth); 122 this.formServiceWidth = this.titleBarWidth - (gridRowUtilsTemp.getSingleColumnWidth() + 123 gridRowUtilsTemp.getGutterX()) * 2; 124 this.gridRowUtils = new GridRowUtils(gridRowUtilsTemp.getColumns() - 2, gridRowUtilsTemp.getGutterX(), 125 this.formServiceWidth); 126 } else { 127 let gridRowUtilsTemp: GridRowUtils = new GridRowUtils(ThisStyleConstants.FORM_SERVICE_GRID_ROW_COLUMNS * 3, 128 ThisStyleConstants.FORM_SERVICE_GRID_ROW_GUTTER_X, this.titleBarWidth); 129 this.formServiceWidth = this.titleBarWidth - (gridRowUtilsTemp.getSingleColumnWidth() + 130 gridRowUtilsTemp.getGutterX()) * 2; 131 this.gridRowUtils = new GridRowUtils(gridRowUtilsTemp.getColumns() - 2, gridRowUtilsTemp.getGutterX(), 132 this.formServiceWidth); 133 } 134 } 135 136 formClick(event: ClickEvent, formItem: CardItemInfo): void { 137 let clickedFormAppInfos: AppItemInfo[] = this.formAppInfos.filter(info => info.bundleName == formItem.bundleName); 138 if (clickedFormAppInfos.length == 0) { 139 Log.showError(TAG, `The clicked card has no app information.`); 140 return; 141 } 142 let formAppInfo: AppItemInfo = clickedFormAppInfos[0]; 143 if (SettingsModel.getInstance().getDevice() == CommonConstants.DEFAULT_DEVICE_TYPE) { 144 this.mFormModel.doBeforeJumpToFormManager(formAppInfo.bundleName).then(() => { 145 AppStorage.setOrCreate('formAppInfo', formAppInfo); 146 windowManager.createWindowWithName(windowManager.FORM_MANAGER_WINDOW_NAME, windowManager.RECENT_RANK); 147 }) 148 } else { 149 this.clickedformApp = JSON.parse(JSON.stringify(formAppInfo)); 150 this.formManagerDialogController?.open(); 151 } 152 } 153 154 formManagerDialogController: CustomDialogController | null = new CustomDialogController({ 155 builder: FormManagerDialog({ 156 cancel: (callback?: () => void) => { 157 // delete all form 158 if (callback !== undefined) { 159 this.clearForm = callback; 160 } else { 161 Log.showError(TAG, `FormManagerDialog callback error`); // 维测日志 162 } 163 }, 164 confirm: (formCardItem: CardItemInfo) => { 165 PageDesktopViewModel.getInstance().createCardToDeskTop(formCardItem); 166 }, 167 bundleName: this.clickedformApp.bundleName as string, 168 appName: this.clickedformApp.appName as string, 169 appLabelId: this.clickedformApp.appLabelId as number 170 }), 171 cancel: this.cancelFormDialog, 172 autoCancel: true, 173 customStyle: true 174 }); 175 176 /** 177 * When click cancel dialog, this function will be called. 178 */ 179 cancelFormDialog(): void { 180 this.clearForm(); 181 } 182 183 formAppClick = (event: ClickEvent, appItem: AppItemInfo): void => { 184 if (SettingsModel.getInstance().getDevice() == CommonConstants.DEFAULT_DEVICE_TYPE) { 185 this.mFormModel.doBeforeJumpToFormManager(appItem.bundleName).then(() => { 186 AppStorage.setOrCreate('formAppInfo', appItem); 187 windowManager.createWindowWithName(windowManager.FORM_MANAGER_WINDOW_NAME, windowManager.RECENT_RANK); 188 }) 189 } else { 190 this.clickedformApp = appItem; 191 this.formManagerDialogController?.open(); 192 } 193 } 194 195 private getFormWidth(dimension?: number): number { 196 if (dimension == CommonConstants.CARD_DIMENSION_2x4) { 197 return this.gridRowUtils.getSpanWidth(4); 198 } 199 if (dimension == CommonConstants.CARD_DIMENSION_2x2) { 200 return this.gridRowUtils.getSpanWidth(2); 201 } 202 return 0; 203 } 204 205 private getFormHeight(dimension?: number): number { 206 if (dimension == CommonConstants.CARD_DIMENSION_2x4 207 || dimension == CommonConstants.CARD_DIMENSION_2x2) { 208 return this.gridRowUtils.getSpanWidth(2); 209 } 210 return 0; 211 } 212 213 @Builder FormMenuBuilder(formItem: CardItemInfo) { 214 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 215 AppMenu({ 216 menuInfoList: this.createAddFormToDesktopMenuInfo(formItem) 217 }) 218 } 219 } 220 221 /** 222 * 添加卡片至桌面 223 * 224 * @param formInfo 卡片信息 225 */ 226 private createAddFormToDesktopMenuInfo(formItem: CardItemInfo): MenuInfo[] { 227 let menuInfoList: MenuInfo[] = new Array<MenuInfo>(); 228 let addFormToDesktopMenuInfo: MenuInfo = new MenuInfo(); 229 addFormToDesktopMenuInfo.menuType = CommonConstants.MENU_TYPE_FIXED; 230 addFormToDesktopMenuInfo.menuImgSrc = '/common/pics/ic_form_addToDesktop.svg'; 231 addFormToDesktopMenuInfo.menuText = $r('app.string.add_to_desktop'); 232 addFormToDesktopMenuInfo.onMenuClick = (): void => { 233 localEventManager.sendLocalEventSticky(EventConstants.EVENT_OPEN_FOLDER_TO_CLOSE, null); 234 let formInfo: CardItemInfo = this.getChoosedCard(formItem); 235 PageDesktopViewModel.getInstance().createCardToDeskTop(formInfo); 236 this.backToDeskTop(); 237 }; 238 menuInfoList.push(addFormToDesktopMenuInfo); 239 return menuInfoList; 240 } 241 242 private getChoosedCard(choosedItem: CardItemInfo): CardItemInfo { 243 let formItem = choosedItem; 244 formItem.cardId = choosedItem.cardId; 245 formItem.cardName = choosedItem.cardName; 246 formItem.cardDimension = choosedItem.cardDimension; 247 formItem.dragLayerWidth = this.getFormWidth(formItem.cardDimension) * 1.05; 248 formItem.dragLayerHeight = this.getFormHeight(formItem.cardDimension) * 1.05; 249 return formItem; 250 } 251 252 build() { 253 Stack() { 254 Column() { 255 Row() { 256 Image(ThisStyleConstants.FORM_SERVICE_BACK_IMAGE) 257 .width(ThisStyleConstants.FORM_SERVICE_BACK_ICON_WIDTH) 258 .height(ThisStyleConstants.FORM_SERVICE_BACK_ICON_HEIGHT) 259 .onClick(() => { 260 this.backToDeskTop(); 261 }) 262 263 Text($r('app.string.add_form_to_desktop')) 264 .textAlign(TextAlign.Start) 265 .textOverflow({ overflow: TextOverflow.Ellipsis }) 266 .maxLines(1) 267 .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle')) 268 .fontColor($r('sys.color.ohos_id_color_text_primary_contrary')) 269 .fontWeight(ResourceManager.getInstance().getFontWeightMedium()) 270 .margin({ 271 left: ThisStyleConstants.FORM_SERVICE_BAR_TEXT_MARGIN_LEFT 272 }) 273 } 274 .width(this.titleBarWidth) 275 .height(ThisStyleConstants.FORM_SERVICE_BAR_HEIGHT) 276 .margin({ 277 top: this.sysUITopHeight 278 }) 279 280 Scroll(this.scroller) { 281 Column() { 282 Column() { 283 GridRow({ 284 columns: this.gridRowUtils.getColumns(), 285 gutter: { 286 x: this.gridRowUtils.getGutterX(), 287 y: $r('sys.float.ohos_id_card_margin_middle') 288 } 289 }) { 290 ForEach(this.showFormInfos, (item: CardItemInfo, index: number) => { 291 GridCol({ 292 span: item.cardDimension == CommonConstants.CARD_DIMENSION_2x4 ? 4 : 2 293 }) { 294 ServiceFormItem({ 295 formItem: item, 296 mFormItemWidth: this.getFormWidth(item.cardDimension), 297 mFormItemHeight: this.getFormHeight(item.cardDimension), 298 idIndex: index 299 }) 300 .bindContextMenu(this.FormMenuBuilder(item), ResponseType.LongPress) 301 .bindContextMenu(this.FormMenuBuilder(item), ResponseType.RightClick) 302 .onClick((event: ClickEvent) => { 303 this.formClick(event, item); 304 }) 305 } 306 }, (item: CardItemInfo) => JSON.stringify(item)) 307 } 308 } 309 .width(this.formServiceWidth) 310 .margin({ 311 top: $r('sys.float.ohos_id_card_margin_middle') 312 }) 313 314 List() { 315 ForEach(this.formAppInfos, (item: AppItemInfo, index: number) => { 316 ListItem() { 317 ServiceFormAppItem({ 318 appName: item.appName, 319 bundleName: item.bundleName, 320 abilityName: item.abilityName, 321 moduleName: item.moduleName, 322 appLabelId: Number(item.appLabelId).valueOf(), 323 iconId: item.appIconId, 324 item: item, 325 clickApp: this.formAppClick, 326 idIndex: index 327 }) 328 } 329 }, (item: AppItemInfo) => JSON.stringify(item)) 330 } 331 .scrollBar(BarState.Off) 332 .divider({ 333 strokeWidth: ThisStyleConstants.SERVICE_FORM_APP_ITEM_GROUP_DIVIDER_WIDTH, 334 color: ThisStyleConstants.FORM_SERVICE_APP_LIST_DIVIDER_COLOR, 335 startMargin: ThisStyleConstants.SERVICE_FORM_APP_ITEM_GROUP_DIVIDER_MARGIN_LEFT, 336 endMargin: 0 337 }) 338 .borderRadius(this.cornerRadiusDefaultL) 339 .width(this.formServiceWidth) 340 .backgroundColor(ThisStyleConstants.FORM_SERVICE_APP_LIST_BACKGROUND_COLOR) 341 .padding({ 342 top: ThisStyleConstants.FORM_SERVICE_APP_LIST_PADDING_VERTICAL, 343 bottom: ThisStyleConstants.FORM_SERVICE_APP_LIST_PADDING_VERTICAL, 344 left: ThisStyleConstants.FORM_SERVICE_APP_LIST_PADDING_HORIZONTAL, 345 right: ThisStyleConstants.FORM_SERVICE_APP_LIST_PADDING_HORIZONTAL 346 }) 347 .margin({ 348 top: $r('sys.float.ohos_id_card_margin_middle'), 349 bottom: ThisStyleConstants.FORM_SERVICE_APP_LIST_MARGIN_BOTTOM 350 }) 351 } 352 .width(StyleConstants.PERCENTAGE_100) 353 .alignItems(HorizontalAlign.Center) 354 } 355 .align(Alignment.TopStart) 356 .scrollBar(BarState.Off) 357 .width(StyleConstants.PERCENTAGE_100) 358 .height(this.scrollerWrapHeight) 359 } 360 .width(StyleConstants.PERCENTAGE_100) 361 .height(StyleConstants.PERCENTAGE_100) 362 } 363 .width(StyleConstants.PERCENTAGE_100) 364 .height(StyleConstants.PERCENTAGE_100) 365 .backgroundImage(StyleConstants.DEFAULT_FORM_MGR_BACKGROUND_IMAGE) 366 .backgroundBlurStyle(BlurStyle.BACKGROUND_THICK) 367 } 368} 369