forked from open-webui/open-webui
		
	feat: response notification
This commit is contained in:
		
							parent
							
								
									ffaa1b17c5
								
							
						
					
					
						commit
						e34b452509
					
				
					 3 changed files with 100 additions and 33 deletions
				
			
		|  | @ -49,8 +49,10 @@ | ||||||
| 	let pullProgress = null; | 	let pullProgress = null; | ||||||
| 
 | 
 | ||||||
| 	// Addons | 	// Addons | ||||||
|  | 	let responseNotification = false; | ||||||
| 	let titleAutoGenerate = true; | 	let titleAutoGenerate = true; | ||||||
| 	let speechAutoSend = false; | 	let speechAutoSend = false; | ||||||
|  | 
 | ||||||
| 	let gravatarEmail = ''; | 	let gravatarEmail = ''; | ||||||
| 	let OPENAI_API_KEY = ''; | 	let OPENAI_API_KEY = ''; | ||||||
| 
 | 
 | ||||||
|  | @ -108,6 +110,19 @@ | ||||||
| 		saveSettings({ titleAutoGenerate: titleAutoGenerate }); | 		saveSettings({ titleAutoGenerate: titleAutoGenerate }); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	const toggleResponseNotification = async () => { | ||||||
|  | 		const permission = await Notification.requestPermission(); | ||||||
|  | 
 | ||||||
|  | 		if (permission === 'granted') { | ||||||
|  | 			responseNotification = !responseNotification; | ||||||
|  | 			saveSettings({ responseNotification: responseNotification }); | ||||||
|  | 		} else { | ||||||
|  | 			toast.error( | ||||||
|  | 				'Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.' | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	const toggleAuthHeader = async () => { | 	const toggleAuthHeader = async () => { | ||||||
| 		authEnabled = !authEnabled; | 		authEnabled = !authEnabled; | ||||||
| 	}; | 	}; | ||||||
|  | @ -802,44 +817,66 @@ | ||||||
| 					> | 					> | ||||||
| 						<div class=" space-y-3"> | 						<div class=" space-y-3"> | ||||||
| 							<div> | 							<div> | ||||||
| 								<div class=" py-1 flex w-full justify-between"> | 								<div class=" mb-1 text-sm font-medium">WebUI Add-ons</div> | ||||||
| 									<div class=" self-center text-sm font-medium">Title Auto Generation</div> |  | ||||||
| 
 | 
 | ||||||
| 									<button | 								<div> | ||||||
| 										class="p-1 px-3 text-xs flex rounded transition" | 									<div class=" py-0.5 flex w-full justify-between"> | ||||||
| 										on:click={() => { | 										<div class=" self-center text-xs font-medium">Response Notification</div> | ||||||
| 											toggleTitleAutoGenerate(); | 
 | ||||||
| 										}} | 										<button | ||||||
| 										type="button" | 											class="p-1 px-3 text-xs flex rounded transition" | ||||||
| 									> | 											on:click={() => { | ||||||
| 										{#if titleAutoGenerate === true} | 												toggleResponseNotification(); | ||||||
| 											<span class="ml-2 self-center">On</span> | 											}} | ||||||
| 										{:else} | 											type="button" | ||||||
| 											<span class="ml-2 self-center">Off</span> | 										> | ||||||
| 										{/if} | 											{#if responseNotification === true} | ||||||
| 									</button> | 												<span class="ml-2 self-center">On</span> | ||||||
|  | 											{:else} | ||||||
|  | 												<span class="ml-2 self-center">Off</span> | ||||||
|  | 											{/if} | ||||||
|  | 										</button> | ||||||
|  | 									</div> | ||||||
| 								</div> | 								</div> | ||||||
| 							</div> |  | ||||||
| 
 | 
 | ||||||
| 							<hr class=" dark:border-gray-700" /> | 								<div> | ||||||
|  | 									<div class=" py-0.5 flex w-full justify-between"> | ||||||
|  | 										<div class=" self-center text-xs font-medium">Title Auto Generation</div> | ||||||
| 
 | 
 | ||||||
| 							<div> | 										<button | ||||||
| 								<div class=" py-1 flex w-full justify-between"> | 											class="p-1 px-3 text-xs flex rounded transition" | ||||||
| 									<div class=" self-center text-sm font-medium">Voice Input Auto-Send</div> | 											on:click={() => { | ||||||
|  | 												toggleTitleAutoGenerate(); | ||||||
|  | 											}} | ||||||
|  | 											type="button" | ||||||
|  | 										> | ||||||
|  | 											{#if titleAutoGenerate === true} | ||||||
|  | 												<span class="ml-2 self-center">On</span> | ||||||
|  | 											{:else} | ||||||
|  | 												<span class="ml-2 self-center">Off</span> | ||||||
|  | 											{/if} | ||||||
|  | 										</button> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
| 
 | 
 | ||||||
| 									<button | 								<div> | ||||||
| 										class="p-1 px-3 text-xs flex rounded transition" | 									<div class=" py-0.5 flex w-full justify-between"> | ||||||
| 										on:click={() => { | 										<div class=" self-center text-xs font-medium">Voice Input Auto-Send</div> | ||||||
| 											toggleSpeechAutoSend(); | 
 | ||||||
| 										}} | 										<button | ||||||
| 										type="button" | 											class="p-1 px-3 text-xs flex rounded transition" | ||||||
| 									> | 											on:click={() => { | ||||||
| 										{#if speechAutoSend === true} | 												toggleSpeechAutoSend(); | ||||||
| 											<span class="ml-2 self-center">On</span> | 											}} | ||||||
| 										{:else} | 											type="button" | ||||||
| 											<span class="ml-2 self-center">Off</span> | 										> | ||||||
| 										{/if} | 											{#if speechAutoSend === true} | ||||||
| 									</button> | 												<span class="ml-2 self-center">On</span> | ||||||
|  | 											{:else} | ||||||
|  | 												<span class="ml-2 self-center">Off</span> | ||||||
|  | 											{/if} | ||||||
|  | 										</button> | ||||||
|  | 									</div> | ||||||
| 								</div> | 								</div> | ||||||
| 							</div> | 							</div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -222,6 +222,21 @@ | ||||||
| 									eval_duration: data.eval_duration | 									eval_duration: data.eval_duration | ||||||
| 								}; | 								}; | ||||||
| 								messages = messages; | 								messages = messages; | ||||||
|  | 
 | ||||||
|  | 								if ($settings.responseNotification && !document.hasFocus()) { | ||||||
|  | 									const notification = new Notification( | ||||||
|  | 										selectedModelfile | ||||||
|  | 											? `${ | ||||||
|  | 													selectedModelfile.title.charAt(0).toUpperCase() + | ||||||
|  | 													selectedModelfile.title.slice(1) | ||||||
|  | 											  }` | ||||||
|  | 											: `Ollama - ${model}`, | ||||||
|  | 										{ | ||||||
|  | 											body: responseMessage.content, | ||||||
|  | 											icon: selectedModelfile?.imageUrl ?? '/favicon.png' | ||||||
|  | 										} | ||||||
|  | 									); | ||||||
|  | 								} | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -234,6 +234,21 @@ | ||||||
| 									eval_duration: data.eval_duration | 									eval_duration: data.eval_duration | ||||||
| 								}; | 								}; | ||||||
| 								messages = messages; | 								messages = messages; | ||||||
|  | 
 | ||||||
|  | 								if ($settings.responseNotification && !document.hasFocus()) { | ||||||
|  | 									const notification = new Notification( | ||||||
|  | 										selectedModelfile | ||||||
|  | 											? `${ | ||||||
|  | 													selectedModelfile.title.charAt(0).toUpperCase() + | ||||||
|  | 													selectedModelfile.title.slice(1) | ||||||
|  | 											  }` | ||||||
|  | 											: `Ollama - ${model}`, | ||||||
|  | 										{ | ||||||
|  | 											body: responseMessage.content, | ||||||
|  | 											icon: selectedModelfile?.imageUrl ?? '/favicon.png' | ||||||
|  | 										} | ||||||
|  | 									); | ||||||
|  | 								} | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek