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