mirror of
				https://github.com/smartfrigde/armcord.git
				synced 2024-08-14 23:56:58 +00:00 
			
		
		
		
	add multi instance
This commit is contained in:
		
							parent
							
								
									5ec56c8cc1
								
							
						
					
					
						commit
						831d45dc45
					
				
					 7 changed files with 44 additions and 6 deletions
				
			
		|  | @ -24,6 +24,8 @@ | ||||||
|     "settings-mintoTray-desc": "When disabled, ArmCord will close like any other window when closed, otherwise it'll sit back and relax\n                in your system tray for later.", |     "settings-mintoTray-desc": "When disabled, ArmCord will close like any other window when closed, otherwise it'll sit back and relax\n                in your system tray for later.", | ||||||
|     "settings-startMinimized": "Start minimized", |     "settings-startMinimized": "Start minimized", | ||||||
|     "settings-startMinimized-desc": "ArmCord starts in background and remains out of your way.", |     "settings-startMinimized-desc": "ArmCord starts in background and remains out of your way.", | ||||||
|  |     "settings-MultiInstance": "Multi Instance", | ||||||
|  |     "settings-MultiInstance-desc": "When enabled you'll be able to start up many instances of ArmCord.", | ||||||
|     "settings-patches": "Automatic Patches", |     "settings-patches": "Automatic Patches", | ||||||
|     "settings-useLegacyCapturer": "Use legacy capturer", |     "settings-useLegacyCapturer": "Use legacy capturer", | ||||||
|     "settings-useLegacyCapturer-desc": "Use legacy screenshare module, instead of the new one. If you're experiencing issues with screen sharing, try enabling this.", |     "settings-useLegacyCapturer-desc": "Use legacy screenshare module, instead of the new one. If you're experiencing issues with screen sharing, try enabling this.", | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ | ||||||
|         "@typescript-eslint/eslint-plugin": "^5.59.2", |         "@typescript-eslint/eslint-plugin": "^5.59.2", | ||||||
|         "@typescript-eslint/parser": "^5.59.2", |         "@typescript-eslint/parser": "^5.59.2", | ||||||
|         "copyfiles": "^2.4.1", |         "copyfiles": "^2.4.1", | ||||||
|         "electron": "26.0.0-beta.11", |         "electron": "26.0.0", | ||||||
|         "electron-builder": "^24.6.3", |         "electron-builder": "^24.6.3", | ||||||
|         "eslint": "^8.40.0", |         "eslint": "^8.40.0", | ||||||
|         "eslint-config-dmitmel": "github:dmitmel/eslint-config-dmitmel", |         "eslint-config-dmitmel": "github:dmitmel/eslint-config-dmitmel", | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							|  | @ -41,8 +41,8 @@ devDependencies: | ||||||
|     specifier: ^2.4.1 |     specifier: ^2.4.1 | ||||||
|     version: 2.4.1 |     version: 2.4.1 | ||||||
|   electron: |   electron: | ||||||
|     specifier: 26.0.0-beta.11 |     specifier: 26.0.0 | ||||||
|     version: 26.0.0-beta.11 |     version: 26.0.0 | ||||||
|   electron-builder: |   electron-builder: | ||||||
|     specifier: ^24.6.3 |     specifier: ^24.6.3 | ||||||
|     version: 24.6.3 |     version: 24.6.3 | ||||||
|  | @ -624,6 +624,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /boolean@3.2.0: |   /boolean@3.2.0: | ||||||
|     resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} |     resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -891,6 +892,7 @@ packages: | ||||||
|   /define-properties@1.1.4: |   /define-properties@1.1.4: | ||||||
|     resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} |     resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} | ||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       has-property-descriptors: 1.0.0 |       has-property-descriptors: 1.0.0 | ||||||
|       object-keys: 1.1.1 |       object-keys: 1.1.1 | ||||||
|  | @ -904,6 +906,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /detect-node@2.1.0: |   /detect-node@2.1.0: | ||||||
|     resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} |     resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -1024,8 +1027,8 @@ packages: | ||||||
|       - supports-color |       - supports-color | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|   /electron@26.0.0-beta.11: |   /electron@26.0.0: | ||||||
|     resolution: {integrity: sha512-QejgSimxMxl4C3oOVGqKPn9T50PHt//i9JZPN3mOKviyawpfA3yI8SbtDhXW0d+6f+GGHIg0Eo7deppki3be/Q==} |     resolution: {integrity: sha512-x57bdCaDvgnlc41VOm/UWihJCCiI3OxJKiBgB/e5F7Zd6avo+61mO6IzQS7Bu/k/a1KPjou25EUORR6UPKznBQ==} | ||||||
|     engines: {node: '>= 12.20.55'} |     engines: {node: '>= 12.20.55'} | ||||||
|     hasBin: true |     hasBin: true | ||||||
|     requiresBuild: true |     requiresBuild: true | ||||||
|  | @ -1052,6 +1055,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /es6-error@4.1.1: |   /es6-error@4.1.1: | ||||||
|     resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} |     resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -1406,6 +1410,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /get-intrinsic@1.1.3: |   /get-intrinsic@1.1.3: | ||||||
|     resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} |     resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       function-bind: 1.1.1 |       function-bind: 1.1.1 | ||||||
|       has: 1.0.3 |       has: 1.0.3 | ||||||
|  | @ -1468,6 +1473,7 @@ packages: | ||||||
|   /globalthis@1.0.3: |   /globalthis@1.0.3: | ||||||
|     resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} |     resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} | ||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       define-properties: 1.1.4 |       define-properties: 1.1.4 | ||||||
|     dev: true |     dev: true | ||||||
|  | @ -1517,6 +1523,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /has-property-descriptors@1.0.0: |   /has-property-descriptors@1.0.0: | ||||||
|     resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} |     resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       get-intrinsic: 1.1.3 |       get-intrinsic: 1.1.3 | ||||||
|     dev: true |     dev: true | ||||||
|  | @ -1525,6 +1532,7 @@ packages: | ||||||
|   /has-symbols@1.0.3: |   /has-symbols@1.0.3: | ||||||
|     resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} |     resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} | ||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -1731,6 +1739,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /json-stringify-safe@5.0.1: |   /json-stringify-safe@5.0.1: | ||||||
|     resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} |     resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -1802,6 +1811,7 @@ packages: | ||||||
|   /matcher@3.0.0: |   /matcher@3.0.0: | ||||||
|     resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} |     resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} | ||||||
|     engines: {node: '>=10'} |     engines: {node: '>=10'} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       escape-string-regexp: 4.0.0 |       escape-string-regexp: 4.0.0 | ||||||
|     dev: true |     dev: true | ||||||
|  | @ -1934,6 +1944,7 @@ packages: | ||||||
|   /object-keys@1.1.1: |   /object-keys@1.1.1: | ||||||
|     resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} |     resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} | ||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -2156,6 +2167,7 @@ packages: | ||||||
|   /roarr@2.15.4: |   /roarr@2.15.4: | ||||||
|     resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} |     resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} | ||||||
|     engines: {node: '>=8.0'} |     engines: {node: '>=8.0'} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       boolean: 3.2.0 |       boolean: 3.2.0 | ||||||
|       detect-node: 2.1.0 |       detect-node: 2.1.0 | ||||||
|  | @ -2192,6 +2204,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /semver-compare@1.0.0: |   /semver-compare@1.0.0: | ||||||
|     resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} |     resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -2219,6 +2232,7 @@ packages: | ||||||
|   /serialize-error@7.0.1: |   /serialize-error@7.0.1: | ||||||
|     resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} |     resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} | ||||||
|     engines: {node: '>=10'} |     engines: {node: '>=10'} | ||||||
|  |     requiresBuild: true | ||||||
|     dependencies: |     dependencies: | ||||||
|       type-fest: 0.13.1 |       type-fest: 0.13.1 | ||||||
|     dev: true |     dev: true | ||||||
|  | @ -2291,6 +2305,7 @@ packages: | ||||||
| 
 | 
 | ||||||
|   /sprintf-js@1.1.2: |   /sprintf-js@1.1.2: | ||||||
|     resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} |     resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  | @ -2433,6 +2448,7 @@ packages: | ||||||
|   /type-fest@0.13.1: |   /type-fest@0.13.1: | ||||||
|     resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} |     resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} | ||||||
|     engines: {node: '>=10'} |     engines: {node: '>=10'} | ||||||
|  |     requiresBuild: true | ||||||
|     dev: true |     dev: true | ||||||
|     optional: true |     optional: true | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import { | ||||||
|     checkIfConfigExists, |     checkIfConfigExists, | ||||||
|     firstRun, |     firstRun, | ||||||
|     getConfig, |     getConfig, | ||||||
|  |     getConfigSync, | ||||||
|     injectElectronFlags, |     injectElectronFlags, | ||||||
|     installModLoader, |     installModLoader, | ||||||
|     modInstallState, |     modInstallState, | ||||||
|  | @ -54,10 +55,12 @@ async function args(): Promise<void> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| args(); // i want my top level awaits
 | args(); // i want my top level awaits
 | ||||||
| if (!app.requestSingleInstanceLock()) { | if (!app.requestSingleInstanceLock() && getConfigSync("multiInstance") == (false ?? undefined)) { | ||||||
|  |     // if value isn't set after 3.2.4
 | ||||||
|     // kill if 2nd instance
 |     // kill if 2nd instance
 | ||||||
|     app.quit(); |     app.quit(); | ||||||
| } else { | } else { | ||||||
|  |     app.commandLine.appendSwitch("disable-features", "WidgetLayering"); // fix dev tools layers
 | ||||||
|     // Your data now belongs to CCP
 |     // Your data now belongs to CCP
 | ||||||
|     crashReporter.start({uploadToServer: false}); |     crashReporter.start({uploadToServer: false}); | ||||||
|     // enable webrtc capturer for wayland
 |     // enable webrtc capturer for wayland
 | ||||||
|  |  | ||||||
|  | @ -80,6 +80,14 @@ | ||||||
|         </div> |         </div> | ||||||
|         <br /> |         <br /> | ||||||
| 
 | 
 | ||||||
|  |         <div class="switch acMultiInstance"> | ||||||
|  |             <label class="header" data-string="settings-MultiInstance"></label> | ||||||
|  |             <input id="mInstance" class="tgl tgl-light left" data-setting="multiInstance" type="checkbox" /> | ||||||
|  |             <label class="tgl-btn left" for="mInstance"></label> | ||||||
|  |             <p class="description" data-string="settings-MultiInstance-desc"></p> | ||||||
|  |         </div> | ||||||
|  |         <br /> | ||||||
|  | 
 | ||||||
|         <div class="switch acWebsocket"> |         <div class="switch acWebsocket"> | ||||||
|             <label class="header" data-string="settings-invitewebsocket"></label> |             <label class="header" data-string="settings-invitewebsocket"></label> | ||||||
|             <input id="websocket" class="tgl tgl-light left" data-setting="inviteWebsocket" type="checkbox" /> |             <input id="websocket" class="tgl tgl-light left" data-setting="inviteWebsocket" type="checkbox" /> | ||||||
|  |  | ||||||
|  | @ -140,6 +140,7 @@ | ||||||
|                         disableAutogain: false, |                         disableAutogain: false, | ||||||
|                         mods: options.mod, |                         mods: options.mod, | ||||||
|                         dynamicIcon: false, |                         dynamicIcon: false, | ||||||
|  |                         multiInstance: false, | ||||||
|                         useLegacyCapturer: false, |                         useLegacyCapturer: false, | ||||||
|                         tray: /true/i.test(document.getElementById("tray").value), |                         tray: /true/i.test(document.getElementById("tray").value), | ||||||
|                         startMinimized: false, |                         startMinimized: false, | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ export function setup(): void { | ||||||
|         automaticPatches: false, |         automaticPatches: false, | ||||||
|         keybinds: [], |         keybinds: [], | ||||||
|         alternativePaste: false, |         alternativePaste: false, | ||||||
|  |         multiInstance: false, | ||||||
|         mods: "none", |         mods: "none", | ||||||
|         spellcheck: true, |         spellcheck: true, | ||||||
|         performanceMode: "none", |         performanceMode: "none", | ||||||
|  | @ -253,6 +254,7 @@ export interface Settings { | ||||||
|     minimizeToTray: boolean; |     minimizeToTray: boolean; | ||||||
|     automaticPatches: boolean; |     automaticPatches: boolean; | ||||||
|     alternativePaste: boolean; |     alternativePaste: boolean; | ||||||
|  |     multiInstance: boolean; | ||||||
|     spellcheck: boolean; |     spellcheck: boolean; | ||||||
|     mods: string; |     mods: string; | ||||||
|     dynamicIcon: boolean; |     dynamicIcon: boolean; | ||||||
|  | @ -282,6 +284,12 @@ export async function getConfig<K extends keyof Settings>(object: K): Promise<Se | ||||||
|     console.log(`[Config manager] ${object}: ${returndata[object]}`); |     console.log(`[Config manager] ${object}: ${returndata[object]}`); | ||||||
|     return returndata[object]; |     return returndata[object]; | ||||||
| } | } | ||||||
|  | export function getConfigSync<K extends keyof Settings>(object: K) { | ||||||
|  |     let rawdata = fs.readFileSync(getConfigLocation(), "utf-8"); | ||||||
|  |     let returndata = JSON.parse(rawdata); | ||||||
|  |     console.log(`[Config manager] ${object}: ${returndata[object]}`); | ||||||
|  |     return returndata[object]; | ||||||
|  | } | ||||||
| export async function setConfig<K extends keyof Settings>(object: K, toSet: Settings[K]): Promise<void> { | export async function setConfig<K extends keyof Settings>(object: K, toSet: Settings[K]): Promise<void> { | ||||||
|     let rawdata = fs.readFileSync(getConfigLocation(), "utf-8"); |     let rawdata = fs.readFileSync(getConfigLocation(), "utf-8"); | ||||||
|     let parsed = JSON.parse(rawdata); |     let parsed = JSON.parse(rawdata); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue