• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2020 The Android Open Source Project
2//
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
15import {RecordConfig} from '../common/state';
16import {validateRecordConfig} from '../controller/validate_config';
17
18const LOCAL_STORAGE_RECORD_CONFIGS_KEY = 'recordConfigs';
19
20class NamedRecordConfig {
21  title: string;
22  config: RecordConfig;
23  key: string;
24
25  constructor(title: string, config: RecordConfig, key: string) {
26    this.title = title;
27    this.config = this.validateData(config);
28    this.key = key;
29  }
30
31  private validateData(config: {}): RecordConfig {
32    const validConfig = validateRecordConfig(config);
33    if (validConfig.errorMessage) {
34      // TODO(bsebastien): Show a warning message to the user in the UI.
35      console.warn(validConfig.errorMessage);
36    }
37    return validConfig.config;
38  }
39
40  static isValid(jsonObject: object): jsonObject is NamedRecordConfig {
41    return (jsonObject as NamedRecordConfig).title !== undefined &&
42        (jsonObject as NamedRecordConfig).config !== undefined &&
43        (jsonObject as NamedRecordConfig).key !== undefined;
44  }
45}
46
47export class RecordConfigStore {
48  recordConfigs: NamedRecordConfig[];
49
50  constructor() {
51    this.recordConfigs = [];
52    this.reloadFromLocalStorage();
53  }
54
55  save(recordConfig: RecordConfig, title?: string): void {
56    // We reload from local storage in case of concurrent
57    // modifications of local storage from a different tab.
58    this.reloadFromLocalStorage();
59
60    const config = new NamedRecordConfig(
61        title ? title : new Date().toJSON(), recordConfig, new Date().toJSON());
62
63    this.recordConfigs.push(config);
64    window.localStorage.setItem(
65        LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
66  }
67
68  delete(key: string): void {
69    // We reload from local storage in case of concurrent
70    // modifications of local storage from a different tab.
71    this.reloadFromLocalStorage();
72
73    let idx = -1;
74    for (let i = 0; i < this.recordConfigs.length; ++i) {
75      if (this.recordConfigs[i].key === key) {
76        idx = i;
77        break;
78      }
79    }
80
81    if (idx !== -1) {
82      this.recordConfigs.splice(idx, 1);
83      window.localStorage.setItem(
84          LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
85    } else {
86      // TODO(bsebastien): Show a warning message to the user in the UI.
87      console.warn('The config selected doesn\'t exist any more');
88    }
89  }
90
91  private clearRecordConfigs(): void {
92    this.recordConfigs = [];
93    window.localStorage.setItem(
94        LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify([]));
95  }
96
97  reloadFromLocalStorage(): void {
98    const configsLocalStorage =
99        window.localStorage.getItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY);
100
101    if (configsLocalStorage) {
102      try {
103        const validConfigLocalStorage: NamedRecordConfig[] = [];
104        const parsedConfigsLocalStorage = JSON.parse(configsLocalStorage);
105
106        // Check if it's an array.
107        if (!Array.isArray(parsedConfigsLocalStorage)) {
108          this.clearRecordConfigs();
109          return;
110        }
111
112        for (let i = 0; i < parsedConfigsLocalStorage.length; ++i) {
113          if (!NamedRecordConfig.isValid(parsedConfigsLocalStorage[i])) {
114            continue;
115          }
116          validConfigLocalStorage.push(new NamedRecordConfig(
117              parsedConfigsLocalStorage[i].title,
118              parsedConfigsLocalStorage[i].config,
119              parsedConfigsLocalStorage[i].key));
120        }
121
122        this.recordConfigs = validConfigLocalStorage;
123        window.localStorage.setItem(
124            LOCAL_STORAGE_RECORD_CONFIGS_KEY,
125            JSON.stringify(validConfigLocalStorage));
126      } catch (e) {
127        this.clearRecordConfigs();
128      }
129    } else {
130      this.clearRecordConfigs();
131    }
132  }
133}
134
135// This class is a singleton to avoid many instances
136// conflicting as they attempt to edit localStorage.
137export const recordConfigStore = new RecordConfigStore();
138