• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 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
16
17import { BaseElement, element } from '../../base-ui/BaseElement.js';
18
19@element('sp-flags')
20export class SpFlags extends BaseElement {
21  private bodyEl: HTMLElement | undefined | null;
22
23  initElements(): void {
24    let parentElement = this.parentNode as HTMLElement;
25    parentElement.style.overflow = 'hidden';
26    this.bodyEl = this.shadowRoot?.querySelector('.body');
27    this.initConfigList();
28  }
29
30  initHtml(): string {
31    return `
32        ${this.initHtmlStyle()}
33        <div class="sp-flags-container">
34         <div class="body">
35           <h3 class="title">Feature flags</h3>
36         </div>
37        </div>
38        `;
39  }
40
41  private initHtmlStyle(): string {
42    return `
43      <style>
44        .sp-flags-container {
45          background-color: var(--dark-background5,#F6F6F6);
46          min-height: 100%;
47          display: grid;
48          grid-template-columns: 1fr;
49          grid-template-rows:1fr;
50        }
51        :host{
52          width: 100%;
53          height: 100%;
54          background-color: var(--dark-background5,#F6F6F6);
55          display: block;
56        }
57        .body{
58          width: 85%;
59          margin: 2% 5% 2% 5%;
60          background-color: var(--dark-background3,#FFFFFF);
61          border-radius: 16px 16px 16px 16px;
62          padding-left: 2%;
63          padding-right: 4%;
64        }
65        .title {
66          padding-left: 2%;
67          margin-left: 8%;
68        }
69        .flag-widget {
70          width: 80%;
71          padding: 1% 2% 1% 2%;
72          margin-left: 8%;
73          margin-right: 8%;
74          border-radius: 10px 10px 10px 10px;
75        }
76        .flag-widget:nth-child(2n+1) {
77          background-color: #F5F5F5;
78        }
79        .flag-title-label {
80          margin-right: 10px;
81          flex-grow: 1;
82          text-align: left;
83          opacity: 0.9;
84          font-family: Helvetica-Bold;
85          font-size: 16px;
86          color: #000000;
87          line-height: 28px;
88          font-weight: 700;
89        }
90        .flag-head-div {
91          display: flex;
92          align-items: center;
93        }
94        .flag-des-div {
95          opacity: 0.6;
96          font-family: Helvetica;
97          font-size: 12px;
98          color: var(--dark-color,#000000);
99          text-align: left;
100          line-height: 20px;
101          font-weight: 400;
102          margin-top: 0.1%;
103        }
104        .config_footer {
105          margin-top: 1%;
106        }
107        .flag-select {
108          width: 12rem;
109          border: 1px solid var(--dark-color1,#4D4D4D);
110          border-radius: 16px;
111          opacity: 0.6;
112          font-family: Helvetica;
113          font-size: 12px;
114          color: var(--dark-color1,#000000);
115          text-align: center;
116          line-height: 20px;
117          font-weight: 400;
118          -webkit-appearance: none;
119          background: url(img/down.png) no-repeat 96% center;
120        }
121        .device_label {
122          font-weight: 500;
123          margin-right: 10px;
124          opacity: 0.9;
125          font-family: Helvetica-Bold;
126          font-size: 14px;
127        }
128        .device_input {
129          line-height: 20px;
130          font-weight: 400;
131          margin-right: 2%;
132          border-radius: 16px;
133          border: 1px solid #ccc;
134          padding-left: 10px;
135        }
136        </style>
137    `;
138  }
139
140  private createConfigDiv(): HTMLDivElement {
141    let configDiv = document.createElement('div');
142    configDiv.className = 'flag-widget';
143    return configDiv;
144  }
145
146  private createCustomDiv(config: FlagConfigItem, configDiv: HTMLDivElement): void {
147    let configHadDiv = document.createElement('div');
148    configHadDiv.className = 'flag-head-div';
149    let titleLabel = document.createElement('label');
150    titleLabel.textContent = config.title;
151    titleLabel.className = 'flag-title-label';
152    let configSelect = document.createElement('select');
153    configSelect.className = 'flag-select';
154    configSelect.setAttribute('title', config.title);
155    config.switchOptions.forEach((optionItem) => {
156      let configOption = document.createElement('option');
157      configOption.value = optionItem.option;
158      configOption.textContent = optionItem.option;
159      if (optionItem.selected) {
160        configOption.selected = true;
161      }
162      configSelect.appendChild(configOption);
163    });
164    configSelect.addEventListener('change', () => {
165      let title = configSelect.getAttribute('title');
166      FlagsConfig.updateFlagsConfig(title!, configSelect.selectedOptions[0].value);
167    });
168    let description = document.createElement('div');
169    description.className = 'flag-des-div';
170    description.textContent = config.describeContent;
171    configHadDiv.appendChild(titleLabel);
172    configHadDiv.appendChild(configSelect);
173    configDiv.appendChild(configHadDiv);
174    configDiv.appendChild(description);
175  }
176
177  private initConfigList(): void {
178    let allConfig = FlagsConfig.getAllFlagConfig();
179    allConfig.forEach((config) => {
180      let configDiv = this.createConfigDiv();
181      this.createCustomDiv(config, configDiv);
182      if (config.title === 'AnimationAnalysis') {
183        let configFooterDiv = document.createElement('div');
184        configFooterDiv.className = 'config_footer';
185        let deviceWidthLabelEl = document.createElement('label');
186        deviceWidthLabelEl.className = 'device_label';
187        deviceWidthLabelEl.textContent = 'PhysicalWidth :';
188        let deviceWidthEl = document.createElement('input');
189        deviceWidthEl.value = <string> config.addInfo!.physicalWidth;
190        deviceWidthEl.addEventListener('keyup', () => {
191          deviceWidthEl.value = deviceWidthEl.value.replace(/\D/g, '');
192        });
193        deviceWidthEl.addEventListener('blur', () => {
194          if (deviceWidthEl.value !== '') {
195            FlagsConfig.updateFlagsConfig('physicalWidth', Number(deviceWidthEl.value));
196          }
197        });
198        deviceWidthEl.className = 'device_input';
199        let deviceHeightLabelEl = document.createElement('label');
200        deviceHeightLabelEl.textContent = 'PhysicalHeight :';
201        deviceHeightLabelEl.className = 'device_label';
202        let deviceHeightEl = document.createElement('input');
203        deviceHeightEl.className = 'device_input';
204        deviceHeightEl.value = <string> config.addInfo!.physicalHeight;
205        deviceHeightEl.addEventListener('keyup', () => {
206          deviceHeightEl.value = deviceHeightEl.value.replace(/\D/g, '');
207        });
208        deviceHeightEl.addEventListener('blur', () => {
209          if (deviceWidthEl.value !== '') {
210            FlagsConfig.updateFlagsConfig('physicalHeight', Number(deviceHeightEl.value));
211          }
212        });
213        configFooterDiv.appendChild(deviceWidthLabelEl);
214        configFooterDiv.appendChild(deviceWidthEl);
215        configFooterDiv.appendChild(deviceHeightLabelEl);
216        configFooterDiv.appendChild(deviceHeightEl);
217        configDiv.appendChild(configFooterDiv);
218      }
219      this.bodyEl!.appendChild(configDiv);
220    });
221  }
222}
223
224export type Params = {
225  [key: string]: unknown;
226};
227
228export class FlagsConfig {
229  static FLAGS_CONFIG_KEY = 'FlagsConfig';
230  static DEFAULT_CONFIG: Array<FlagConfigItem> = [
231    {
232      title: 'TaskPool',
233      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
234      describeContent: 'Analyze TaskPool templates',
235    },
236    {
237      title: 'AnimationAnalysis',
238      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
239      describeContent: 'Analyze Animation effect templates',
240      addInfo: { physicalWidth: 0, physicalHeight: 0 }
241    },
242    {
243      title: 'AppStartup',
244      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
245      describeContent: 'App Startup templates',
246    },
247    {
248      title: 'SchedulingAnalysis',
249      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
250      describeContent: 'Scheduling analysis templates',
251    },
252  ];
253
254  static getAllFlagConfig(): Array<FlagConfigItem> {
255    let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
256    if (flagsConfigStr === null) {
257      let flagConfigObj: Params = {};
258      FlagsConfig.DEFAULT_CONFIG.forEach((config) => {
259        let selectedOption = config.switchOptions.filter((option) => {
260          return option.selected;
261        });
262        let value = config.switchOptions[0].option;
263        if (selectedOption[0] !== undefined) {
264          value = selectedOption[0].option;
265        }
266        flagConfigObj[config.title] = value;
267        if (config.addInfo) {
268          for (const [key, value] of Object.entries(config.addInfo)) {
269            flagConfigObj[key] = value;
270          }
271        }
272      });
273      window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj));
274      return FlagsConfig.DEFAULT_CONFIG;
275    } else {
276      let flagsConfig = JSON.parse(flagsConfigStr);
277      FlagsConfig.DEFAULT_CONFIG.forEach((config) => {
278        let cfg = flagsConfig[config.title];
279        if (cfg) {
280          config.switchOptions.forEach((option) => {
281            if (option.option === cfg) {
282              option.selected = true;
283            } else {
284              option.selected = false;
285            }
286          });
287        }
288        if (config.addInfo) {
289          for (const [key, value] of Object.entries(config.addInfo)) {
290            let cfg = flagsConfig[key];
291            if (cfg) {
292              config.addInfo[key] = cfg;
293            }
294          }
295        }
296      });
297    }
298    return FlagsConfig.DEFAULT_CONFIG;
299  }
300
301  static getSpTraceStreamParseConfig(): string {
302    let parseConfig = {};
303    FlagsConfig.getAllFlagConfig().forEach(
304      configItem => {
305        let selectedOption = configItem.switchOptions.filter((option) => {
306          return option.selected;
307        });
308        // @ts-ignore
309        parseConfig[configItem.title] = selectedOption[0].option === 'Enabled' ? 1 : 0;
310      }
311    );
312    return JSON.stringify({ 'config': parseConfig });
313  }
314
315  static getFlagsConfig(flagName: string): Params | undefined {
316    let flagConfigObj: Params = {};
317    let configItem = FlagsConfig.getAllFlagConfig().find((config) => {
318      return config.title === flagName;
319    });
320    if (configItem) {
321      let selectedOption = configItem.switchOptions.filter((option) => {
322        return option.selected;
323      });
324      let value = configItem.switchOptions[0].option;
325      if (selectedOption[0] !== undefined) {
326        value = selectedOption[0].option;
327      }
328      flagConfigObj[configItem.title] = value;
329      if (configItem.addInfo) {
330        for (const [key, value] of Object.entries(configItem.addInfo)) {
331          flagConfigObj[key] = value;
332        }
333      }
334      return flagConfigObj;
335    } else {
336      return configItem;
337    }
338  }
339
340  static getFlagsConfigEnableStatus(flagName: string): boolean {
341    let config = FlagsConfig.getFlagsConfig(flagName);
342    let enable: boolean = false;
343    if (config && config[flagName]) {
344      enable = config[flagName] === 'Enabled';
345    }
346    return enable;
347  }
348
349  static updateFlagsConfig(key: string, value: unknown): void {
350    let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
351    let flagConfigObj: Params = {};
352    if (flagsConfigStr !== null) {
353      flagConfigObj = JSON.parse(flagsConfigStr);
354    }
355    flagConfigObj[key] = value;
356    window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj));
357  }
358}
359
360export interface FlagConfigItem {
361  title: string;
362  switchOptions: OptionItem[];
363  describeContent: string;
364  addInfo?: Params;
365}
366
367export interface OptionItem {
368  option: string;
369  selected?: boolean;
370}
371