this repo has no description
at v1.0.1 9.4 kB view raw
1import { 2 DictionarySettingType, 3 ExtensionSettingType, 4 ExtensionSettingsManifest, 5 NumberSettingType, 6 SelectSettingType 7} from "@moonlight-mod/types/config"; 8import WebpackRequire from "@moonlight-mod/types/discord/require"; 9import { MoonbaseExtension } from "../types"; 10 11type SettingsProps = { 12 ext: MoonbaseExtension; 13 name: string; 14 setting: ExtensionSettingsManifest; 15}; 16 17type SettingsComponent = React.ComponentType<SettingsProps>; 18 19export default (require: typeof WebpackRequire) => { 20 const React = require("common_react"); 21 const spacepack = require("spacepack_spacepack"); 22 const CommonComponents = require("common_components"); 23 const Flux = require("common_flux"); 24 25 const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType< 26 typeof import("../stores")["stores"] 27 >; 28 29 function Boolean({ ext, name, setting }: SettingsProps) { 30 const { FormSwitch } = CommonComponents; 31 const { value, displayName } = Flux.useStateFromStores( 32 [MoonbaseSettingsStore], 33 () => { 34 return { 35 value: MoonbaseSettingsStore.getExtensionConfig<boolean>( 36 ext.id, 37 name 38 ), 39 displayName: MoonbaseSettingsStore.getExtensionConfigName( 40 ext.id, 41 name 42 ) 43 }; 44 }, 45 [ext.id, name] 46 ); 47 48 return ( 49 <FormSwitch 50 value={value ?? false} 51 hideBorder={true} 52 onChange={(value: boolean) => { 53 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 54 }} 55 > 56 {displayName} 57 </FormSwitch> 58 ); 59 } 60 61 function Number({ ext, name, setting }: SettingsProps) { 62 const { Slider, ControlClasses } = CommonComponents; 63 const { value, displayName } = Flux.useStateFromStores( 64 [MoonbaseSettingsStore], 65 () => { 66 return { 67 value: MoonbaseSettingsStore.getExtensionConfig<number>(ext.id, name), 68 displayName: MoonbaseSettingsStore.getExtensionConfigName( 69 ext.id, 70 name 71 ) 72 }; 73 }, 74 [ext.id, name] 75 ); 76 77 const castedSetting = setting as NumberSettingType; 78 const min = castedSetting.min ?? 0; 79 const max = castedSetting.max ?? 100; 80 81 return ( 82 <div> 83 <label className={ControlClasses.title}>{displayName}</label> 84 <Slider 85 initialValue={value ?? 0} 86 minValue={castedSetting.min ?? 0} 87 maxValue={castedSetting.max ?? 100} 88 onValueChange={(value: number) => { 89 const rounded = Math.max(min, Math.min(max, Math.round(value))); 90 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, rounded); 91 }} 92 /> 93 </div> 94 ); 95 } 96 97 function String({ ext, name, setting }: SettingsProps) { 98 const { TextInput, ControlClasses } = CommonComponents; 99 const { value, displayName } = Flux.useStateFromStores( 100 [MoonbaseSettingsStore], 101 () => { 102 return { 103 value: MoonbaseSettingsStore.getExtensionConfig<string>(ext.id, name), 104 displayName: MoonbaseSettingsStore.getExtensionConfigName( 105 ext.id, 106 name 107 ) 108 }; 109 }, 110 [ext.id, name] 111 ); 112 113 return ( 114 <div> 115 <label className={ControlClasses.title}>{displayName}</label> 116 <TextInput 117 value={value ?? ""} 118 onChange={(value: string) => { 119 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 120 }} 121 /> 122 </div> 123 ); 124 } 125 126 function Select({ ext, name, setting }: SettingsProps) { 127 const { ControlClasses, SingleSelect } = CommonComponents; 128 const { value, displayName } = Flux.useStateFromStores( 129 [MoonbaseSettingsStore], 130 () => { 131 return { 132 value: MoonbaseSettingsStore.getExtensionConfig<string>(ext.id, name), 133 displayName: MoonbaseSettingsStore.getExtensionConfigName( 134 ext.id, 135 name 136 ) 137 }; 138 }, 139 [ext.id, name] 140 ); 141 142 const castedSetting = setting as SelectSettingType; 143 const options = castedSetting.options; 144 145 return ( 146 <div> 147 <label className={ControlClasses.title}>{displayName}</label> 148 <SingleSelect 149 autofocus={false} 150 clearable={false} 151 value={value ?? ""} 152 options={options.map((o) => ({ value: o, label: o }))} 153 onChange={(value: string) => { 154 MoonbaseSettingsStore.setExtensionConfig(ext.id, name, value); 155 }} 156 /> 157 </div> 158 ); 159 } 160 161 function List({ ext, name, setting }: SettingsProps) { 162 const { ControlClasses, Select, useVariableSelect, multiSelect } = 163 CommonComponents; 164 const { value, displayName } = Flux.useStateFromStores( 165 [MoonbaseSettingsStore], 166 () => { 167 return { 168 value: 169 MoonbaseSettingsStore.getExtensionConfig<string>(ext.id, name) ?? 170 [], 171 displayName: MoonbaseSettingsStore.getExtensionConfigName( 172 ext.id, 173 name 174 ) 175 }; 176 }, 177 [ext.id, name] 178 ); 179 180 const castedSetting = setting as SelectSettingType; 181 const options = castedSetting.options; 182 183 return ( 184 <div> 185 <label className={ControlClasses.title}>{displayName}</label> 186 <Select 187 autofocus={false} 188 clearable={false} 189 options={options.map((o) => ({ value: o, label: o }))} 190 {...useVariableSelect({ 191 onSelectInteraction: multiSelect, 192 value: new Set(Array.isArray(value) ? value : [value]), 193 onChange: (value: string) => { 194 MoonbaseSettingsStore.setExtensionConfig( 195 ext.id, 196 name, 197 Array.from(value) 198 ); 199 } 200 })} 201 /> 202 </div> 203 ); 204 } 205 206 function Dictionary({ ext, name, setting }: SettingsProps) { 207 const { TextInput, ControlClasses, Button, Flex } = CommonComponents; 208 const { value, displayName } = Flux.useStateFromStores( 209 [MoonbaseSettingsStore], 210 () => { 211 return { 212 value: MoonbaseSettingsStore.getExtensionConfig< 213 Record<string, string> 214 >(ext.id, name), 215 displayName: MoonbaseSettingsStore.getExtensionConfigName( 216 ext.id, 217 name 218 ) 219 }; 220 }, 221 [ext.id, name] 222 ); 223 224 const castedSetting = setting as DictionarySettingType; 225 const entries = Object.entries(value ?? {}); 226 227 return ( 228 <Flex direction={Flex.Direction.VERTICAL}> 229 <label className={ControlClasses.title}>{displayName}</label> 230 {entries.map(([key, val], i) => ( 231 // FIXME: stylesheets 232 <div 233 key={i} 234 style={{ 235 display: "grid", 236 height: "40px", 237 gap: "10px", 238 gridTemplateColumns: "1fr 1fr 40px" 239 }} 240 > 241 <TextInput 242 value={key} 243 onChange={(newKey: string) => { 244 entries[i][0] = newKey; 245 MoonbaseSettingsStore.setExtensionConfig( 246 ext.id, 247 name, 248 Object.fromEntries(entries) 249 ); 250 }} 251 /> 252 <TextInput 253 value={val} 254 onChange={(newValue: string) => { 255 entries[i][1] = newValue; 256 MoonbaseSettingsStore.setExtensionConfig( 257 ext.id, 258 name, 259 Object.fromEntries(entries) 260 ); 261 }} 262 /> 263 <Button 264 color={Button.Colors.RED} 265 size={Button.Sizes.ICON} 266 onClick={() => { 267 entries.splice(i, 1); 268 MoonbaseSettingsStore.setExtensionConfig( 269 ext.id, 270 name, 271 Object.fromEntries(entries) 272 ); 273 }} 274 > 275 X 276 </Button> 277 </div> 278 ))} 279 280 <Button 281 look={Button.Looks.FILLED} 282 color={Button.Colors.GREEN} 283 onClick={() => { 284 entries.push([`entry-${entries.length}`, ""]); 285 MoonbaseSettingsStore.setExtensionConfig( 286 ext.id, 287 name, 288 Object.fromEntries(entries) 289 ); 290 }} 291 > 292 Add new entry 293 </Button> 294 </Flex> 295 ); 296 } 297 298 function Setting({ ext, name, setting }: SettingsProps) { 299 const elements: Partial<Record<ExtensionSettingType, SettingsComponent>> = { 300 [ExtensionSettingType.Boolean]: Boolean, 301 [ExtensionSettingType.Number]: Number, 302 [ExtensionSettingType.String]: String, 303 [ExtensionSettingType.Select]: Select, 304 [ExtensionSettingType.List]: List, 305 [ExtensionSettingType.Dictionary]: Dictionary 306 }; 307 const element = elements[setting.type]; 308 if (element == null) return <></>; 309 return React.createElement(element, { ext, name, setting }); 310 } 311 312 function Settings({ ext }: { ext: MoonbaseExtension }) { 313 const { Flex } = CommonComponents; 314 return ( 315 <Flex direction={Flex.Direction.VERTICAL}> 316 {Object.entries(ext.manifest.settings!).map(([name, setting]) => ( 317 <Setting ext={ext} key={name} name={name} setting={setting} /> 318 ))} 319 </Flex> 320 ); 321 } 322 323 return { 324 Boolean, 325 Settings 326 }; 327};