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 { Log } from '@ohos/common'; 17import { Trace } from '@ohos/common'; 18import { StyleConstants } from '@ohos/common'; 19import { PresetStyleConstants } from '@ohos/common'; 20import { AppBubble } from '@ohos/common'; 21import { AppIcon } from '@ohos/common'; 22import { UninstallDialog } from '@ohos/common'; 23import { FormManagerDialog } from '@ohos/common'; 24import { ResourceManager } from '@ohos/common'; 25import { PageDesktopDragHandler } from '../PageDesktopDragHandler'; 26import { CommonConstants } from '@ohos/common'; 27import PageDesktopViewModel from '../../viewmodel/PageDesktopViewModel'; 28import { PageDesktopStartAppHandler } from '../PageDesktopStartAppHandler'; 29 30const DOUBLE_CLICK_COUNT = 2 31 32const TAG = "AppItem"; 33 34@Component 35export default struct AppItem { 36 @StorageLink('dragItemInfo') pageDesktopDragItemInfo: any = {}; 37 @StorageLink('dragItemType') dragItemType: number = CommonConstants.DRAG_FROM_DESKTOP; 38 @StorageLink('uninstallAppInfo') appInfo: any = {}; 39 @StorageLink('formAppInfo') formAppInfo: any = {}; 40 @StorageLink('selectDesktopAppItem') selectDesktopAppItem: string = ''; 41 @State mAppNameHeight: number = StyleConstants.DEFAULT_APP_NAME_HEIGHT; 42 @State mAppItemWidth: number = StyleConstants.DEFAULT_APP_ITEM_WIDTH; 43 @State mAppNameSize: number = StyleConstants.DEFAULT_APP_NAME_SIZE; 44 mNameLines: number = PresetStyleConstants.DEFAULT_APP_NAME_LINES; 45 @State mIconSize: number = StyleConstants.DEFAULT_APP_ICON_SIZE_WIDTH; 46 mIconNameMargin: number = PresetStyleConstants.DEFAULT_ICON_NAME_GAP; 47 private mMargin: number = 0; 48 private mMarginVertical: number = 0; 49 private mGridSpaceWidth : number; 50 private mGridSpaceHeight : number; 51 private isSwappingPage = false; 52 private item: any; 53 private mPageDesktopViewModel: PageDesktopViewModel; 54 private isPad: boolean = false; 55 private mPageDesktopDragHandler: PageDesktopDragHandler; 56 private mPageDesktopStartAppHandler: PageDesktopStartAppHandler; 57 private mouseClick: number = 0; 58 private dialogName: string = ""; 59 private clearForm: Function = null; 60 61 dialogController: CustomDialogController = new CustomDialogController({ 62 builder: UninstallDialog({ 63 cancel: () => {}, 64 confirm: () => { 65 if (this.isPad) { 66 this.mPageDesktopViewModel.deleteAppItem({ 67 bundleName: undefined, 68 keyName: this.appInfo.keyName 69 }); 70 } else { 71 this.mPageDesktopViewModel.uninstallApp(this.appInfo.bundleName, this.appInfo.isUninstallAble); 72 } 73 }, 74 dialogName: this.dialogName, 75 dialogContent: this.appInfo.appName + ' ?', 76 }), 77 cancel: this.cancelDialog, 78 autoCancel: false, 79 customStyle: true 80 }); 81 82 /** 83 * Dialog for form manager view (pad adaptation). 84 */ 85 formManagerDialogController: CustomDialogController = new CustomDialogController({ 86 builder: FormManagerDialog({ 87 cancel: (callback?) => { 88 // delete all form 89 if (callback != undefined) { 90 this.clearForm = callback; 91 } 92 }, 93 confirm: (formCardItem) => { 94 // add form to desktop 95 Log.showInfo(TAG, `createCardToDeskTop formCardItem: ${JSON.stringify(formCardItem)}`); 96 this.mPageDesktopViewModel.createCardToDeskTop(formCardItem); 97 // delete other form 98 }, 99 bundleName: this.formAppInfo.bundleName, 100 appName: this.formAppInfo.appName, 101 appLabelId: this.formAppInfo.appLabelId 102 }), 103 cancel: this.cancelFormDialog, 104 autoCancel: false, 105 customStyle: true 106 }); 107 108 @Builder dragLayerBuilder() { 109 Column() { 110 AppIcon({ 111 iconSize: this.mIconSize * 1.05, 112 iconId: this.item.appIconId, 113 bundleName: this.item.bundleName, 114 moduleName: this.item.moduleName, 115 icon: ResourceManager.getInstance().getCachedAppIcon(this.item.appIconId, this.item.bundleName, this.item.moduleName), 116 badgeNumber: this.item.badgeNumber 117 }) 118 } 119 } 120 121 /** 122 * When click cancel dialog, this function will be called. 123 */ 124 cancelFormDialog() { 125 Log.showInfo(TAG, 'cancel form dialog'); 126 this.clearForm(); 127 } 128 129 aboutToAppear(): void { 130 this.mPageDesktopDragHandler = PageDesktopDragHandler.getInstance(); 131 this.mPageDesktopStartAppHandler = PageDesktopStartAppHandler.getInstance(); 132 this.isPad = this.mPageDesktopViewModel.getDevice(); 133 let styleConfig = this.mPageDesktopViewModel.getPageDesktopStyleConfig(); 134 this.mAppNameHeight = styleConfig.mNameHeight; 135 this.mAppItemWidth = styleConfig.mAppItemSize; 136 this.mAppNameSize = styleConfig.mNameSize; 137 this.mMargin = styleConfig.mMargin; 138 this.mIconSize = styleConfig.mIconSize; 139 this.mMarginVertical = styleConfig.mIconMarginVertical; 140 this.mIconNameMargin = styleConfig.mIconNameMargin; 141 this.mGridSpaceWidth = Number(this.mPageDesktopViewModel.getWorkSpaceWidth()) - this.mMargin; 142 this.mGridSpaceHeight = Number(this.mPageDesktopViewModel.getWorkSpaceHeight()); 143 ResourceManager.getInstance().getStringByResource(this.isPad 144 ? $r('app.string.is_delete_form') : $r('app.string.isUninstall')).then((resName) => { 145 this.dialogName = resName; 146 }); 147 } 148 149 getMenuInfoList() { 150 const menuInfo = this.mPageDesktopViewModel.buildMenuInfoList(this.item, 151 this.dialogController, this.formManagerDialogController) 152 return menuInfo; 153 } 154 155 /** 156 * When click cancel dialog, this function will be called. 157 */ 158 cancelDialog() { 159 Log.showInfo(TAG, 'cancel app uninstall dialog'); 160 } 161 162 build() { 163 Column() { 164 AppBubble({ 165 iconSize: this.mIconSize, 166 nameSize: this.mAppNameSize, 167 nameHeight: this.mAppNameHeight, 168 nameFontColor: this.mPageDesktopViewModel.getPageDesktopStyleConfig().mNameFontColor, 169 appName: this.item.appName, 170 bundleName: this.item.bundleName, 171 abilityName: this.item.abilityName, 172 moduleName: this.item.moduleName, 173 appIconId: this.item.appIconId, 174 appLabelId: this.item.appLabelId, 175 badgeNumber: this.item.badgeNumber, 176 isSelect: this.selectDesktopAppItem == this.item.keyName, 177 getMenuInfoList: this.getMenuInfoList.bind(this), 178 mPaddingTop: this.mMarginVertical, 179 nameLines: this.mNameLines, 180 mIconNameMargin: this.mIconNameMargin, 181 dragStart: this.dragStart.bind(this) 182 }) 183 } 184 .visibility(this.dragItemType === CommonConstants.DRAG_FROM_DESKTOP && this.pageDesktopDragItemInfo.keyName === this.item.keyName ? 185 Visibility.None : Visibility.Visible) 186 .onMouse((event: MouseEvent) => { 187 if (event.button == MouseButton.Right) { 188 event.stopPropagation(); 189 Log.showInfo(TAG, 'onMouse mouse button right'); 190 AppStorage.SetOrCreate('selectDesktopAppItem', this.item.keyName); 191 } 192 }) 193 .onClick((event) => { 194 Log.showInfo(TAG, `tap action ${JSON.stringify(event)}`); 195 if (event.source == SourceType.Mouse) { 196 this.mouseClick++; 197 if (this.mouseClick == DOUBLE_CLICK_COUNT) { 198 Log.showInfo(TAG, 'mouse double click'); 199 this.mouseClick = 0; 200 this.launchApp(); 201 } else { 202 this.mPageDesktopViewModel.onAppClick(this.item.abilityName, this.item.bundleName, this.item.moduleName); 203 setTimeout(() => { 204 this.mouseClick = 0; 205 }, 300) 206 } 207 } else { 208 Log.showInfo(TAG, 'tap click'); 209 this.launchApp(); 210 } 211 }) 212 .onTouch((event: TouchEvent) => { 213 Log.showDebug(TAG, `onTouch event type: ${event.type}, x: ${event.touches[0].screenX}, y: ${event.touches[0].screenY}`); 214 if (event.type === CommonConstants.TOUCH_TYPE_UP && AppStorage.Get('isDrag')) { 215 let mIsDragEffectArea = globalThis.PageDesktopDragHandler.isDragEffectArea(event.touches[0].screenX, event.touches[0].screenY); 216 Log.showInfo(TAG, `onTouch mIsDragEffectArea: ${mIsDragEffectArea}`); 217 if (!mIsDragEffectArea) { 218 this.pageDesktopDragItemInfo = {}; 219 AppStorage.SetOrCreate('selectAppIndex', null); 220 AppStorage.SetOrCreate('isDrag', false); 221 } 222 } 223 }) 224 .width(this.mAppItemWidth) 225 .height(this.mAppItemWidth) 226 } 227 228 /** 229 * When app is double clicked, call this method. 230 */ 231 private launchApp() { 232 Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION); 233 this.setStartAppInfo(); 234 this.mPageDesktopViewModel.onAppDoubleClick(this.item.abilityName, this.item.bundleName, this.item.moduleName); 235 } 236 237 dragStart(event: DragEvent): CustomBuilder { 238 AppStorage.SetOrCreate('isDrag', true); 239 ContextMenu.close(); 240 this.dragItemType = CommonConstants.DRAG_FROM_DESKTOP; 241 this.pageDesktopDragItemInfo = this.item; 242 Log.showInfo(TAG, `pageDesktopDragItemInfo: ${JSON.stringify(this.pageDesktopDragItemInfo)}`); 243 globalThis.PageDesktopDragHandler.onDragStart(event.getX(), event.getY()); 244 return this.dragLayerBuilder(); 245 } 246 247 /** 248 * set start app info 249 */ 250 private setStartAppInfo() { 251 Log.showInfo(TAG, `app setStartAppInfo ${this.mIconSize}`); 252 Trace.start("setStartAppInfo"); 253 const appInfo = { 254 bundleName: this.item.bundleName, 255 abilityName: this.item.abilityName, 256 moduleName: this.item.moduleName, 257 appIconSize: this.mIconSize, 258 appIconId: this.item.appIconId, 259 icon: ResourceManager.getInstance() 260 .getCachedAppIcon(this.item.appIconId, this.item.bundleName, this.item.moduleName), 261 row: this.item.row, 262 column: this.item.column 263 } 264 AppStorage.SetOrCreate('startAppItemInfo', appInfo); 265 AppStorage.SetOrCreate('startAppTypeFromPageDesktop', CommonConstants.OVERLAY_TYPE_APP_ICON); 266 this.mPageDesktopStartAppHandler.setAppIconSize(this.mIconSize); 267 this.mPageDesktopStartAppHandler.setAppIconInfo(); 268 Trace.end("setStartAppInfo"); 269 } 270}