1/* 2 * Copyright (c) 2021-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 16/** 17 * Environment 18 * 19 * Injects device properties ("environment") into AppStorage 20 * 21 */ 22 23class Environment { 24 private static instance_: Environment = undefined; 25 private static envBackend_: IEnvironmentBackend; 26 private props_: Map<string, SubscribedAbstractProperty<any>>; 27 28 private static getOrCreate(): Environment { 29 if (Environment.instance_) { 30 // already initialized 31 return Environment.instance_; 32 } 33 34 Environment.instance_ = new Environment(); 35 return Environment.instance_; 36 } 37 38 public static configureBackend(envBackend: IEnvironmentBackend): void { 39 Environment.envBackend_ = envBackend; 40 } 41 42 /** 43 * @see configureBackend 44 * @deprecated 45 */ 46 public static ConfigureBackend(envBackend: IEnvironmentBackend): void { 47 Environment.envBackend_ = envBackend; 48 } 49 50 51 public static aboutToBeDeleted(): void { 52 if (!Environment.instance_) { 53 return; 54 } 55 56 Environment.getOrCreate().aboutToBeDeleted(); 57 Environment.instance_ = undefined; 58 } 59 60 /** 61 * @see aboutToBeDeleted 62 * @deprecated 63 */ 64 public static AboutToBeDeleted(): void { 65 Environment.aboutToBeDeleted(); 66 } 67 68 public static envProp<S>(key: string, value: S): boolean { 69 return Environment.getOrCreate().envProp<S>(key, value); 70 } 71 72 /** 73 * @see envProp 74 * @deprecated 75 */ 76 public static EnvProp<S>(key: string, value: S): boolean { 77 return Environment.getOrCreate().envProp<S>(key, value); 78 } 79 80 public static envProps(props: { 81 key: string, 82 defaultValue: any 83 }[] 84 ): void { 85 Environment.getOrCreate().envProps(props); 86 } 87 88 /** 89 * @see envProps 90 * @deprecated 91 */ 92 public static EnvProps(props: { 93 key: string, 94 defaultValue: any 95 }[] 96 ): void { 97 Environment.getOrCreate().envProps(props); 98 } 99 100 static keys(): Array<string> { 101 return Environment.getOrCreate().keys(); 102 } 103 104 /** 105 * @see keys 106 * @deprecated 107 */ 108 static Keys(): Array<string> { 109 return Environment.getOrCreate().keys(); 110 } 111 112 private constructor() { 113 this.props_ = new Map<string, ObservedPropertyAbstract<any>>(); 114 115 Environment.envBackend_.onValueChanged(this.onValueChanged.bind(this)); 116 } 117 118 private envProp<S>(key: string, value: S): boolean { 119 let prop = AppStorage.prop(key); 120 if (prop) { 121 stateMgmtConsole.warn(`Environment: envProp '${key}': Property already exists in AppStorage. Not using environment property.`); 122 return false; 123 } 124 let tmp; 125 switch (key) { 126 case 'accessibilityEnabled': 127 tmp = Environment.envBackend_ .getAccessibilityEnabled(); 128 break; 129 case 'colorMode': 130 tmp = Environment.envBackend_ .getColorMode(); 131 break; 132 case 'fontScale': 133 tmp = Environment.envBackend_ .getFontScale(); 134 break; 135 case 'fontWeightScale': 136 tmp = Environment.envBackend_ .getFontWeightScale().toFixed(2); 137 break; 138 case 'layoutDirection': 139 tmp = Environment.envBackend_ .getLayoutDirection(); 140 break; 141 case 'languageCode': 142 tmp = Environment.envBackend_ .getLanguageCode(); 143 break; 144 default: 145 tmp = value; 146 } 147 if (!tmp && tmp !== 0) { 148 tmp = value; 149 } 150 prop = AppStorage.setAndProp(key, tmp); 151 if (!prop) { 152 stateMgmtConsole.warn(`Environment: envProp '${key}': AppStorage setAndProp failed.`); 153 return false; 154 } 155 this.props_.set(key, prop); 156 stateMgmtConsole.debug(`Environment: envProp for '${key}' done.`); 157 return true; 158 } 159 160 private envProps(properties: { 161 key: string, 162 defaultValue: any 163 }[]): void { 164 properties.forEach(property => { 165 this.envProp(property.key, property.defaultValue); 166 stateMgmtConsole.debug(`Environment: envProps for '${property.key}' done.`); 167 }); 168 } 169 170 keys(): Array<string> { 171 let result = []; 172 const it = this.props_.keys(); 173 let val = it.next(); 174 175 while (!val.done) { 176 result.push(val.value); 177 val = it.next(); 178 } 179 180 return result; 181 } 182 183 onValueChanged(key: string, value: any): void { 184 let ok = AppStorage.set(key, value); 185 if (ok) { 186 stateMgmtConsole.debug(`Environment: onValueChanged: ${key} changed to ${value}`); 187 } else { 188 stateMgmtConsole.warn(`Environment: onValueChanged: error changing ${key}! See results above.`); 189 } 190 } 191 192 aboutToBeDeleted() { 193 this.props_.forEach((val, key, map) => { 194 val.aboutToBeDeleted(); 195 AppStorage.delete(key); 196 }); 197 } 198} 199