feat: follow requests in sidebar
This commit is contained in:
		
							parent
							
								
									0dd903a4eb
								
							
						
					
					
						commit
						6f446fd871
					
				
					 6 changed files with 117 additions and 3 deletions
				
			
		|  | @ -23,6 +23,7 @@ | ||||||
|     "navigation": { |     "navigation": { | ||||||
|         "timeline": "Timeline", |         "timeline": "Timeline", | ||||||
|         "notifications": "Notifications", |         "notifications": "Notifications", | ||||||
|  |         "follow_requests": "Follow requests", | ||||||
|         "explore": "Explore", |         "explore": "Explore", | ||||||
|         "lists": "Lists", |         "lists": "Lists", | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -176,6 +176,32 @@ export async function getNotifications(host, token, min_id, max_id, limit, types | ||||||
|     return data; |     return data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * GET /api/v1/follow_requests | ||||||
|  |  * @param {string} host - The domain of the target server. | ||||||
|  |  * @param {string} token - The application token. | ||||||
|  |  * @param {string} min_id - If provided, only shows follow requests since this ID. | ||||||
|  |  * @param {string} max_id - If provided, only shows follow requests before this ID. | ||||||
|  |  * @param {string} limit - The maximum number of follow requests to retrieve (default 40, max 80). | ||||||
|  |  */ | ||||||
|  | export async function getFollowRequests(host, token, since_id, max_id, limit) { | ||||||
|  |     let url = `https://${host}/api/v1/follow_requests`; | ||||||
|  | 
 | ||||||
|  |     let params = new URLSearchParams(); | ||||||
|  |     if (since_id) params.append("since_id", since_id); | ||||||
|  |     if (max_id) params.append("max_id", max_id); | ||||||
|  |     if (limit) params.append("limit", limit); | ||||||
|  |     const params_string = params.toString(); | ||||||
|  |     if (params_string) url += '?' + params_string; | ||||||
|  | 
 | ||||||
|  |     const data = await fetch(url, { | ||||||
|  |         method: 'GET', | ||||||
|  |         headers: { "Authorization": "Bearer " + token } | ||||||
|  |     }).then(res => res.json()); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * GET /api/v1/timelines/{timeline} |  * GET /api/v1/timelines/{timeline} | ||||||
|  * @param {string} host - The domain of the target server. |  * @param {string} host - The domain of the target server. | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								src/lib/followRequests.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/lib/followRequests.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | import { server } from './client/server.js'; | ||||||
|  | import { writable } from "svelte/store"; | ||||||
|  | import * as api from "./api.js"; | ||||||
|  | import { app } from './client/app.js'; | ||||||
|  | import { get } from 'svelte/store'; | ||||||
|  | 
 | ||||||
|  | // Cache for all requests
 | ||||||
|  | export let followRequests = writable(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets all follow requests | ||||||
|  |  * @param {boolean} force | ||||||
|  |  */ | ||||||
|  | export async function fetchFollowRequests(force) { | ||||||
|  |     // if already cached, return for now
 | ||||||
|  |     if(!get(followRequests) && !force) return; | ||||||
|  | 
 | ||||||
|  |     let newReqs = await api.getFollowRequests( | ||||||
|  |         get(server).host, | ||||||
|  |         get(app).token | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     followRequests.set(newReqs); | ||||||
|  | } | ||||||
|  | @ -6,8 +6,9 @@ | ||||||
|     import { playSound } from '$lib/sound.js'; |     import { playSound } from '$lib/sound.js'; | ||||||
|     import { goto } from '$app/navigation'; |     import { goto } from '$app/navigation'; | ||||||
|     import { page } from '$app/stores'; |     import { page } from '$app/stores'; | ||||||
|     import { createEventDispatcher } from 'svelte'; |     import { createEventDispatcher, onMount } from 'svelte'; | ||||||
|     import { unread_notif_count } from '$lib/notifications.js'; |     import { unread_notif_count } from '$lib/notifications.js'; | ||||||
|  |     import { fetchFollowRequests, followRequests } from '$lib/followRequests.js' | ||||||
|     import Lang from '$lib/lang'; |     import Lang from '$lib/lang'; | ||||||
| 
 | 
 | ||||||
|     import Logo from '$lib/../img/campfire-logo.svg'; |     import Logo from '$lib/../img/campfire-logo.svg'; | ||||||
|  | @ -24,6 +25,7 @@ | ||||||
|     import InfoIcon from '../../img/icons/info.svg'; |     import InfoIcon from '../../img/icons/info.svg'; | ||||||
|     import SettingsIcon from '../../img/icons/settings.svg'; |     import SettingsIcon from '../../img/icons/settings.svg'; | ||||||
|     import LogoutIcon from '../../img/icons/logout.svg'; |     import LogoutIcon from '../../img/icons/logout.svg'; | ||||||
|  |     import FollowersIcon from '../../img/icons/followers.svg'; | ||||||
| 
 | 
 | ||||||
|     const VERSION = APP_VERSION; |     const VERSION = APP_VERSION; | ||||||
|     const lang = Lang('en_GB'); |     const lang = Lang('en_GB'); | ||||||
|  | @ -40,7 +42,7 @@ | ||||||
|         goto(`/${$server.host}/${$account.username}`); |         goto(`/${$server.host}/${$account.username}`); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async function log_out() { |     async function logOut() { | ||||||
|         if (!confirm("This will log you out. Are you sure?")) return; |         if (!confirm("This will log you out. Are you sure?")) return; | ||||||
|          |          | ||||||
|         const res = await api.revokeToken( |         const res = await api.revokeToken( | ||||||
|  | @ -59,6 +61,10 @@ | ||||||
| 
 | 
 | ||||||
|         goto("/"); |         goto("/"); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     onMount(async () => { | ||||||
|  |         await fetchFollowRequests(true) | ||||||
|  |     }) | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <div id="navigation"> | <div id="navigation"> | ||||||
|  | @ -91,6 +97,19 @@ | ||||||
|                 </span> |                 </span> | ||||||
|             {/if} |             {/if} | ||||||
|         </Button> |         </Button> | ||||||
|  |         {#if $followRequests.length > 0} | ||||||
|  |             <Button label="Follow requests" | ||||||
|  |                     href="/follow-requests"} | ||||||
|  |                     active={$page.url.pathname === "/follow-requests"}> | ||||||
|  |                 <svelte:fragment slot="icon"> | ||||||
|  |                     <FollowersIcon/> | ||||||
|  |                 </svelte:fragment> | ||||||
|  |                 {lang.string('navigation.follow_requests')} | ||||||
|  |                 <span class="notification-count"> | ||||||
|  |                     {$followRequests.length} | ||||||
|  |                 </span> | ||||||
|  |             </Button> | ||||||
|  |         {/if} | ||||||
|         <Button label="Explore" disabled> |         <Button label="Explore" disabled> | ||||||
|             <svelte:fragment slot="icon"> |             <svelte:fragment slot="icon"> | ||||||
|                 <ExploreIcon height="auto"/> |                 <ExploreIcon height="auto"/> | ||||||
|  | @ -142,7 +161,7 @@ | ||||||
|                     <SettingsIcon/> |                     <SettingsIcon/> | ||||||
|                 </svelte:fragment> |                 </svelte:fragment> | ||||||
|             </Button> |             </Button> | ||||||
|             <Button centered label="{lang.string('navigation.log_out')}" on:click={() => log_out()}> |             <Button centered label="{lang.string('navigation.log_out')}" on:click={() => logOut()}> | ||||||
|                 <svelte:fragment slot="icon"> |                 <svelte:fragment slot="icon"> | ||||||
|                     <LogoutIcon/> |                     <LogoutIcon/> | ||||||
|                 </svelte:fragment> |                 </svelte:fragment> | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								src/lib/ui/core/PageHeader.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/lib/ui/core/PageHeader.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | ||||||
|  | <script> | ||||||
|  |     export let title; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <header> | ||||||
|  |     <h1>{title}</h1> | ||||||
|  |     <slot name="icon" /> | ||||||
|  | </header> | ||||||
|  | 
 | ||||||
|  | <style> | ||||||
|  |     header { | ||||||
|  |         width: 100%; | ||||||
|  |         height: 64px; | ||||||
|  |         margin: 16px 0; | ||||||
|  |         padding: 0 8px; | ||||||
|  |         display: flex; | ||||||
|  |         flex-direction: row; | ||||||
|  |         user-select: none; | ||||||
|  |         box-sizing: border-box; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     header h1 { | ||||||
|  |         font-size: 1.5em; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     nav { | ||||||
|  |         margin-left: auto; | ||||||
|  |         display: flex; | ||||||
|  |         flex-direction: row; | ||||||
|  |         align-items: center; | ||||||
|  |         gap: 8px; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
							
								
								
									
										10
									
								
								src/routes/follow-requests/+page.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/routes/follow-requests/+page.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | <script> | ||||||
|  |     import { followRequests } from '$lib/followRequests.js'; | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <div> | ||||||
|  | 
 | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <style></style> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue