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 */ 15 16const pip = requireNapi('pip'); 17const NodeController = requireNapi('arkui.node').NodeController; 18const FrameNode = requireNapi('arkui.node').FrameNode; 19 20const TAG = 'PiPContent'; 21const ABOUT_TO_STOP = 3; 22 23class XCNodeController extends NodeController { 24 constructor(m2) { 25 super(); 26 this.node = null; 27 this.mXComponent = m2; 28 } 29 makeNode(l2) { 30 this.node = new FrameNode(l2); 31 this.node.appendChild(this.mXComponent); 32 return this.node; 33 } 34 replaceNode(k) { 35 this.node?.removeChild(this.mXComponent); 36 this.mXComponent = k; 37 this.node?.appendChild(this.mXComponent); 38 } 39 removeNode() { 40 this.node?.removeChild(this.mXComponent); 41 } 42} 43 44class PiPContent extends ViewPU { 45 constructor(f2, g2, h2, i2 = -1, j2 = undefined, k2) { 46 super(f2, h2, i2, k2); 47 if (typeof f2 === 'function') { 48 this.paramsGenerator_ = j2; 49 } 50 this.xComponentController = new XComponentController(); 51 this.nodeController = null; 52 this.mXCNodeController = null; 53 this.__useNode = new ObservedPropertySimplePU(false, this, 'useNode'); 54 this.__nodeChange = new ObservedPropertySimplePU(false, this, 'nodeChange'); 55 this.xComponent = null; 56 this.xComponentId = 'pipContent'; 57 this.xComponentType = 'surface'; 58 this.nodeUpdateListener = (y1) => { 59 console.info(TAG, `nodeUpdate`); 60 if (!this.validateNode(y1)) { 61 return; 62 } 63 if (this.useNode) { 64 pip.setPipNodeType(this.xComponent, false); 65 this.updatePipNodeType(y1); 66 this.mXCNodeController?.replaceNode(y1); 67 this.nodeChange = true; 68 } 69 else { 70 this.updatePipNodeType(y1); 71 this.mXCNodeController = new XCNodeController(y1); 72 console.info(TAG, 'update to Node Controller'); 73 this.registerStateChangeListener(); 74 this.useNode = true; 75 } 76 }; 77 this.stateChangeListener = (x1) => { 78 console.info(TAG, `stateChange state:${x1}`); 79 if (x1 === ABOUT_TO_STOP) { 80 this.mXCNodeController?.removeNode(); 81 } 82 }; 83 this.setInitiallyProvidedValue(g2); 84 } 85 setInitiallyProvidedValue(e2) { 86 if (e2.xComponentController !== undefined) { 87 this.xComponentController = e2.xComponentController; 88 } 89 if (e2.nodeController !== undefined) { 90 this.nodeController = e2.nodeController; 91 } 92 if (e2.mXCNodeController !== undefined) { 93 this.mXCNodeController = e2.mXCNodeController; 94 } 95 if (e2.useNode !== undefined) { 96 this.useNode = e2.useNode; 97 } 98 if (e2.nodeChange !== undefined) { 99 this.nodeChange = e2.nodeChange; 100 } 101 if (e2.xComponent !== undefined) { 102 this.xComponent = e2.xComponent; 103 } 104 if (e2.xComponentId !== undefined) { 105 this.xComponentId = e2.xComponentId; 106 } 107 if (e2.xComponentType !== undefined) { 108 this.xComponentType = e2.xComponentType; 109 } 110 } 111 updateStateVars(d2) { 112 } 113 purgeVariableDependenciesOnElmtId(c2) { 114 if (c2 === null || c2 === undefined) { 115 return; 116 } 117 this.__useNode.purgeDependencyOnElmtId(c2); 118 this.__nodeChange.purgeDependencyOnElmtId(c2); 119 } 120 aboutToBeDeleted() { 121 this.__useNode.aboutToBeDeleted(); 122 this.__nodeChange.aboutToBeDeleted(); 123 SubscriberManager.Get().delete(this.id__()); 124 this.aboutToBeDeletedInternal(); 125 } 126 get useNode() { 127 return this.__useNode.get(); 128 } 129 set useNode(j) { 130 this.__useNode.set(j); 131 } 132 get nodeChange() { 133 return this.__nodeChange.get(); 134 } 135 set nodeChange(i) { 136 this.__nodeChange.set(i); 137 } 138 validateNode(g) { 139 if (g === null || g === undefined) { 140 console.error(TAG, `validateNode node is null`); 141 return false; 142 } 143 let h = g.getNodeType(); 144 if (h !== 'XComponent') { 145 console.error(TAG, `node type mismatch: ${h}`); 146 return false; 147 } 148 return true; 149 } 150 registerUpdateNodeListener() { 151 pip.on('nodeUpdate', this.nodeUpdateListener); 152 } 153 updatePipNodeType(c) { 154 let d = c.getParent(); 155 if (d === null || d === undefined) { 156 pip.setPipNodeType(c, false); 157 } 158 else { 159 pip.setPipNodeType(c, true); 160 d.removeChild(c); 161 } 162 } 163 registerStateChangeListener() { 164 pip.on('stateChange', this.stateChangeListener); 165 } 166 aboutToAppear() { 167 try { 168 this.nodeController = pip.getCustomUIController(); 169 this.registerUpdateNodeListener(); 170 this.xComponent = pip.getTypeNode(); 171 if (!this.validateNode(this.xComponent)) { 172 return; 173 } 174 if (this.xComponent === null) { 175 console.error(TAG, `validateNode node is null`); 176 return; 177 } 178 this.useNode = true; 179 this.updatePipNodeType(this.xComponent); 180 pip.setTypeNodeEnabled(); 181 this.mXCNodeController = new XCNodeController(this.xComponent); 182 console.info(TAG, 'use Node Controller'); 183 this.registerStateChangeListener(); 184 } catch (b) { 185 console.log(`aboutToAppear failed`); 186 } 187 } 188 189 updatePipNodeType(a2) { 190 let b2 = a2.getParent(); 191 if (b2 === null || b2 === undefined) { 192 pip.setPipNodeType(a2, false); 193 } else { 194 pip.setPipNodeType(a2, true); 195 b2.removeChild(a2); 196 } 197 } 198 199 200 aboutToDisappear() { 201 try { 202 pip.off('stateChange', this.stateChangeListener); 203 pip.off('nodeUpdate', this.nodeUpdateListener); 204 } catch (a) { 205 console.log(`aboutToDisappear failed`); 206 } 207 } 208 209 initialRender() { 210 this.observeComponentCreation2((s1, t1) => { 211 Stack.create(); 212 Stack.size({ width: '100%', height: '100%' }); 213 }, Stack); 214 this.observeComponentCreation2((h1, i1) => { 215 If.create(); 216 if (this.useNode || this.nodeChange) { 217 this.ifElseBranchUpdateFunction(0, () => { 218 this.buildNode.bind(this)(); 219 }); 220 } else { 221 this.ifElseBranchUpdateFunction(1, () => { 222 this.buildXComponent.bind(this)(); 223 }); 224 } 225 }, If); 226 If.pop(); 227 this.observeComponentCreation2((a1, b1) => { 228 If.create(); 229 if (this.nodeController !== null) { 230 this.ifElseBranchUpdateFunction(0, () => { 231 this.buildCustomUI.bind(this)(); 232 }); 233 } else { 234 this.ifElseBranchUpdateFunction(1, () => { 235 }); 236 } 237 }, If); 238 If.pop(); 239 Stack.pop(); 240 } 241 242 buildCustomUI(g1 = null) { 243 this.observeComponentCreation2((i1, j1) => { 244 NodeContainer.create(this.nodeController); 245 NodeContainer.size({ width: '100%', height: '100%'}); 246 }, NodeContainer); 247 } 248 249 buildXComponent(b1 = null) { 250 this.observeComponentCreation2((d1, e1) => { 251 XComponent.create({ 252 id: this.xComponentId, 253 type: this.xComponentType, 254 controller: this.xComponentController 255 }, 'pipContent_XComponent'); 256 XComponent.onLoad((() => { 257 pip.initXComponentController(this.xComponentController); 258 console.info(TAG, 'XComponent onLoad done'); 259 })); 260 XComponent.size({ width: '100%', height: '100%' }); 261 XComponent.backgroundColor(Color.Transparent); 262 }, XComponent); 263 } 264 265 buildNode(x = null) { 266 this.observeComponentCreation2((z, a1) => { 267 NodeContainer.create(this.mXCNodeController); 268 NodeContainer.size({ width: '100%', height: '100%' }); 269 }, NodeContainer); 270 } 271 272 rerender() { 273 this.updateDirtyElements(); 274 } 275 276 static getEntryName() { 277 return 'PiPContent'; 278 } 279} 280 281ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); 282loadDocument(new PiPContent(void 0, {})); 283ViewStackProcessor.StopGetAccessRecording();