forked from DebaucheryLibrarian/traxxx
				
			Added dedicated notifications page.
This commit is contained in:
		
							parent
							
								
									3f55b90ab8
								
							
						
					
					
						commit
						83ed793e39
					
				|  | @ -137,7 +137,7 @@ async function fetchEntity(scroll = true) { | |||
| 
 | ||||
| 	this.pageTitle = entity.name; | ||||
| 
 | ||||
| 	if (scroll) { | ||||
| 	if (scroll && this.$refs.filter?.$el) { | ||||
| 		this.$refs.filter.$el.scrollIntoView(); | ||||
| 	} | ||||
| } | ||||
|  | @ -146,9 +146,11 @@ async function mounted() { | |||
| 	await this.fetchEntity(); | ||||
| } | ||||
| 
 | ||||
| async function route() { | ||||
| 	await this.fetchEntity(); | ||||
| 	this.expanded = false; | ||||
| async function route(to) { | ||||
| 	if (to.name === 'channel' || to.name === 'network' || to.name === 'studio') { | ||||
| 		await this.fetchEntity(); | ||||
| 		this.expanded = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
|  |  | |||
|  | @ -96,7 +96,11 @@ | |||
| 				</div> | ||||
| 
 | ||||
| 				<template v-slot:tooltip> | ||||
| 					<Notifications /> | ||||
| 					<Notifications | ||||
| 						:notifications="notifications" | ||||
| 						:unseen-count="unseenNotificationsCount" | ||||
| 						@check="fetchNotifications" | ||||
| 					/> | ||||
| 				</template> | ||||
| 			</Tooltip> | ||||
| 
 | ||||
|  | @ -154,8 +158,11 @@ function me() { | |||
| 	return this.$store.state.auth.user; | ||||
| } | ||||
| 
 | ||||
| function unseenNotificationsCount() { | ||||
| 	return this.$store.state.ui.unseenNotificationsCount; | ||||
| async function fetchNotifications() { | ||||
| 	const { notifications, unseenCount } = await this.$store.dispatch('fetchNotifications'); | ||||
| 
 | ||||
| 	this.notifications = notifications; | ||||
| 	this.unseenNotificationsCount = unseenCount; | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
|  | @ -170,11 +177,19 @@ export default { | |||
| 			logo, | ||||
| 			searching: false, | ||||
| 			showFilters: false, | ||||
| 			notifications: [], | ||||
| 			unseenNotificationsCount: 0, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		me, | ||||
| 		unseenNotificationsCount, | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		me: fetchNotifications, | ||||
| 	}, | ||||
| 	mounted: fetchNotifications, | ||||
| 	methods: { | ||||
| 		fetchNotifications, | ||||
| 	}, | ||||
| }; | ||||
| </script> | ||||
|  |  | |||
|  | @ -5,13 +5,14 @@ | |||
| 
 | ||||
| 			<div class="notifications-actions"> | ||||
| 				<Icon | ||||
| 					v-if="unseenNotificationsCount > 0" | ||||
| 					v-if="unseenCount > 0" | ||||
| 					v-tooltip="'Mark all as seen'" | ||||
| 					icon="checkmark" | ||||
| 					@click="checkNotifications" | ||||
| 				/> | ||||
| 
 | ||||
| 				<Icon | ||||
| 					v-tooltip="'Add alert'" | ||||
| 					icon="plus3" | ||||
| 					@click="showAddAlert = true" | ||||
| 				/> | ||||
|  | @ -111,28 +112,29 @@ | |||
| 				</li> | ||||
| 			</ul> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div @click="$emit('blur')"> | ||||
| 			<router-link | ||||
| 				to="/notifications" | ||||
| 				class="notification-link notification-more" | ||||
| 			>See all</router-link> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import AddAlert from '../alerts/add.vue'; | ||||
| 
 | ||||
| function notifications() { | ||||
| 	return this.$store.state.ui.notifications; | ||||
| } | ||||
| 
 | ||||
| function unseenNotificationsCount() { | ||||
| 	return this.$store.state.ui.unseenNotificationsCount; | ||||
| } | ||||
| 
 | ||||
| async function checkNotifications() { | ||||
| 	await this.$store.dispatch('checkNotifications'); | ||||
| 	await this.$store.dispatch('fetchNotifications'); | ||||
| 
 | ||||
| 	this.$emit('check'); | ||||
| } | ||||
| 
 | ||||
| async function checkNotification(notificationId, blur) { | ||||
| 	await this.$store.dispatch('checkNotification', notificationId); | ||||
| 	await this.$store.dispatch('fetchNotifications'); | ||||
| 
 | ||||
| 	this.$emit('check'); | ||||
| 
 | ||||
| 	if (blur) { | ||||
| 		this.events.emit('blur'); | ||||
|  | @ -143,15 +145,21 @@ export default { | |||
| 	components: { | ||||
| 		AddAlert, | ||||
| 	}, | ||||
| 	props: { | ||||
| 		notifications: { | ||||
| 			type: Array, | ||||
| 			default: () => [], | ||||
| 		}, | ||||
| 		unseenCount: { | ||||
| 			type: Number, | ||||
| 			default: 0, | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			showAddAlert: false, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		notifications, | ||||
| 		unseenNotificationsCount, | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		checkNotifications, | ||||
| 		checkNotification, | ||||
|  | @ -162,6 +170,9 @@ export default { | |||
| <style lang="scss" scoped> | ||||
| .notifications { | ||||
| 	width: 30rem; | ||||
| 	max-height: calc(100vh - 5rem); | ||||
| 	display: flex; | ||||
| 	flex-direction: column; | ||||
| } | ||||
| 
 | ||||
| .notifications-header { | ||||
|  | @ -172,11 +183,15 @@ export default { | |||
| 		padding: .5rem; | ||||
| 		fill: var(--shadow); | ||||
| 
 | ||||
| 		&:last-child { | ||||
| 			padding: .5rem 1rem .5rem .5rem; | ||||
| 		&:first-child { | ||||
| 			padding: .5rem .5rem .5rem 1.5rem; | ||||
| 		} | ||||
| 
 | ||||
| 		:hover { | ||||
| 		&:last-child { | ||||
| 			padding: .5rem 1.5rem .5rem .5rem; | ||||
| 		} | ||||
| 
 | ||||
| 		&:hover { | ||||
| 			fill: var(--primary); | ||||
| 			cursor: pointer; | ||||
| 		} | ||||
|  | @ -193,6 +208,8 @@ export default { | |||
| } | ||||
| 
 | ||||
| .notifications-body { | ||||
| 	flex-grow: 1; | ||||
| 	overflow-y: auto; | ||||
| 	box-shadow: 0 0 3px var(--shadow-weak); | ||||
| } | ||||
| 
 | ||||
|  | @ -204,7 +221,6 @@ export default { | |||
| .notification { | ||||
| 	display: block; | ||||
| 	border-right: solid .5rem var(--shadow-touch); | ||||
| 	margin: 0 0 -1px 0; | ||||
| 	color: var(--text); | ||||
| 
 | ||||
| 	&.unseen { | ||||
|  | @ -215,6 +231,10 @@ export default { | |||
| 		padding: 1.3rem .5rem; | ||||
| 		fill: var(--shadow-weak); | ||||
| 
 | ||||
| 		&.notification-check { | ||||
| 			padding: 1.3rem .5rem 1.3rem 1rem; | ||||
| 		} | ||||
| 
 | ||||
| 		&:last-child { | ||||
| 			padding: 1.3rem 1rem 1.3rem .5rem; | ||||
| 		} | ||||
|  | @ -226,6 +246,7 @@ export default { | |||
| 
 | ||||
| 	&:not(:last-child) { | ||||
| 		border-bottom: solid 1px var(--shadow-hint); | ||||
| 		margin: 0 0 -1px 0; | ||||
| 	} | ||||
| 
 | ||||
| 	&:hover { | ||||
|  | @ -307,6 +328,19 @@ export default { | |||
| 	font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| .notification-more { | ||||
| 	display: block; | ||||
| 	padding: .5rem 1rem; | ||||
| 	color: var(--shadow); | ||||
| 	text-align: center; | ||||
| 	font-size: .9rem; | ||||
| 	font-weight: bold; | ||||
| 
 | ||||
| 	&:hover { | ||||
| 		color: var(--primary); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .poster { | ||||
| 	width: 6rem; | ||||
| 	height: 3.6rem; | ||||
|  |  | |||
|  | @ -0,0 +1,76 @@ | |||
| <template> | ||||
| 	<div | ||||
| 		ref="page" | ||||
| 		class="notifications-container" | ||||
| 	> | ||||
| 		<h1 class="heading">Notifications</h1> | ||||
| 
 | ||||
| 		<ul class="notifications nolist"> | ||||
| 			<li | ||||
| 				v-for="notification in notifications" | ||||
| 				:key="notification.id" | ||||
| 			> | ||||
| 				<SceneTile :release="notification.scene" /> | ||||
| 			</li> | ||||
| 		</ul> | ||||
| 
 | ||||
| 		<Pagination | ||||
| 			:items-total="totalCount" | ||||
| 			:items-per-page="10" | ||||
| 		/> | ||||
| 	</div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import Pagination from '../pagination/pagination.vue'; | ||||
| import SceneTile from '../releases/scene-tile.vue'; | ||||
| 
 | ||||
| async function fetchNotifications() { | ||||
| 	const { notifications, totalCount, unseenCount } = await this.$store.dispatch('fetchNotifications', { | ||||
| 		page: this.$route.params.pageNumber, | ||||
| 		limit: this.limit, | ||||
| 	}); | ||||
| 
 | ||||
| 	this.notifications = notifications; | ||||
| 	this.unseenNotificationsCount = unseenCount; | ||||
| 	this.totalCount = totalCount; | ||||
| 
 | ||||
| 	this.$emit('scroll'); | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
| 	components: { | ||||
| 		Pagination, | ||||
| 		SceneTile, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			notifications: [], | ||||
| 			limit: 10, | ||||
| 			totalCount: 0, | ||||
| 			unseenNotificationsCount: 0, | ||||
| 		}; | ||||
| 	}, | ||||
| 	emits: ['scroll'], | ||||
| 	watch: { | ||||
| 		$route: fetchNotifications, | ||||
| 	}, | ||||
| 	mounted: fetchNotifications, | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .notifications-container { | ||||
| 	padding: 1rem; | ||||
| } | ||||
| 
 | ||||
| .notifications { | ||||
| 	display: grid; | ||||
|     grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr)); | ||||
| 	grid-gap: .5rem; | ||||
| } | ||||
| 
 | ||||
| .pagination { | ||||
| 	margin: 1rem 0 0 0; | ||||
| } | ||||
| </style> | ||||
|  | @ -22,6 +22,8 @@ | |||
| 						:src="getPath(release.poster, 'thumbnail')" | ||||
| 						:style="{ 'background-image': getBgPath(release.poster, 'lazy') }" | ||||
| 						:alt="release.title" | ||||
| 						:width="release.poster.thumbnailWidth" | ||||
| 						:height="release.poster.thumbnailHeight" | ||||
| 						class="thumbnail" | ||||
| 						loading="lazy" | ||||
| 					> | ||||
|  | @ -31,6 +33,8 @@ | |||
| 						:src="getPath(release.photos[0], 'thumbnail')" | ||||
| 						:style="{ 'background-image': getBgPath(release.photos[0], 'lazy') } " | ||||
| 						:alt="release.title" | ||||
| 						:width="release.photos[0].thumbnailWidth" | ||||
| 						:height="release.photos[0].thumbnailHeight" | ||||
| 						class="thumbnail" | ||||
| 						loading="lazy" | ||||
| 					> | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import Networks from '../components/networks/networks.vue'; | |||
| import Actor from '../components/actors/actor.vue'; | ||||
| import Actors from '../components/actors/actors.vue'; | ||||
| import Movies from '../components/releases/movies.vue'; | ||||
| import Notifications from '../components/notifications/notifications.vue'; | ||||
| import Tag from '../components/tags/tag.vue'; | ||||
| import Tags from '../components/tags/tags.vue'; | ||||
| import Stash from '../components/stashes/stash.vue'; | ||||
|  | @ -202,6 +203,20 @@ const routes = [ | |||
| 		component: Tags, | ||||
| 		name: 'tags', | ||||
| 	}, | ||||
| 	{ | ||||
| 		path: '/notifications', | ||||
| 		redirect: { | ||||
| 			name: 'notifications', | ||||
| 			params: { | ||||
| 				pageNumber: 1, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| 	{ | ||||
| 		path: '/notifications/:pageNumber', | ||||
| 		component: Notifications, | ||||
| 		name: 'notifications', | ||||
| 	}, | ||||
| 	{ | ||||
| 		path: '/stash/:stashId/:stashSlug?', | ||||
| 		component: Stash, | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ function initUiActions(store, _router) { | |||
| 		localStorage.setItem('sfw', sfw); | ||||
| 	} | ||||
| 
 | ||||
| 	async function fetchNotifications({ commit }) { | ||||
| 	async function fetchNotifications(_context, { page = 1, limit = 10 } = {}) { | ||||
| 		if (!store.state.auth.user) { | ||||
| 			return []; | ||||
| 		} | ||||
|  | @ -38,44 +38,50 @@ function initUiActions(store, _router) { | |||
|             query Notifications( | ||||
| 				$hasAuth: Boolean! | ||||
| 				$userId: Int | ||||
| 				$limit: Int = 10 | ||||
| 				$offset: Int = 0 | ||||
| 			) { | ||||
|                 notifications( | ||||
| 					first: 10 | ||||
| 				notifications: notificationsConnection( | ||||
| 					first: $limit | ||||
| 					offset: $offset | ||||
| 					orderBy: CREATED_AT_DESC | ||||
| 				) { | ||||
|                     id | ||||
| 					sceneId | ||||
| 					userId | ||||
| 					seen | ||||
| 					createdAt | ||||
| 					scene { | ||||
| 						${releaseFields} | ||||
| 					} | ||||
| 					alert { | ||||
| 						tags: alertsTags { | ||||
| 							tag { | ||||
| 								id | ||||
| 								name | ||||
| 								slug | ||||
| 							} | ||||
| 					nodes { | ||||
| 						id | ||||
| 						sceneId | ||||
| 						userId | ||||
| 						seen | ||||
| 						createdAt | ||||
| 						scene { | ||||
| 							${releaseFields} | ||||
| 						} | ||||
| 						actors: alertsActors { | ||||
| 							actor { | ||||
| 								id | ||||
| 								name | ||||
| 								slug | ||||
| 						alert { | ||||
| 							tags: alertsTags { | ||||
| 								tag { | ||||
| 									id | ||||
| 									name | ||||
| 									slug | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 						entity: alertsEntityByAlertId { | ||||
| 							entity { | ||||
| 								id | ||||
| 								name | ||||
| 								slug | ||||
| 								independent | ||||
| 							actors: alertsActors { | ||||
| 								actor { | ||||
| 									id | ||||
| 									name | ||||
| 									slug | ||||
| 								} | ||||
| 							} | ||||
| 							entity: alertsEntityByAlertId { | ||||
| 								entity { | ||||
| 									id | ||||
| 									name | ||||
| 									slug | ||||
| 									independent | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
|                 } | ||||
| 					totalCount | ||||
| 				} | ||||
| 				unseenNotifications: notificationsConnection( | ||||
| 					filter: { seen: { equalTo: false } } | ||||
| 				) { | ||||
|  | @ -85,15 +91,15 @@ function initUiActions(store, _router) { | |||
|         `, {
 | ||||
| 			hasAuth: !!store.state.auth.user, | ||||
| 			userId: store.state.auth.user?.id, | ||||
| 			limit, | ||||
| 			offset: (page - 1) * limit, | ||||
| 		}); | ||||
| 
 | ||||
| 		const curatedNotifications = notifications.map(notification => curateNotification(notification)); | ||||
| 
 | ||||
| 		commit('setNotifications', curatedNotifications); | ||||
| 		commit('setUnseenNotificationsCount', unseenNotifications.totalCount); | ||||
| 		const curatedNotifications = notifications.nodes.map(notification => curateNotification(notification)); | ||||
| 
 | ||||
| 		return { | ||||
| 			notifications: curatedNotifications, | ||||
| 			totalCount: notifications.totalCount, | ||||
| 			unseenCount: unseenNotifications.totalCount, | ||||
| 		}; | ||||
| 	} | ||||
|  | @ -207,6 +213,8 @@ function initUiActions(store, _router) { | |||
| 			userId: store.state.auth.user?.id, | ||||
| 		}); | ||||
| 
 | ||||
| 		console.log(res.results); | ||||
| 
 | ||||
| 		return { | ||||
| 			releases: res?.results.map(result => curateRelease(result.release)) || [], | ||||
| 			actors: res?.actors.map(actor => curateActor(actor)) || [], | ||||
|  |  | |||
|  | @ -1,11 +1,3 @@ | |||
| function setNotifications(state, notifications) { | ||||
| 	state.notifications = notifications; | ||||
| } | ||||
| 
 | ||||
| function setUnseenNotificationsCount(state, count) { | ||||
| 	state.unseenNotificationsCount = count; | ||||
| } | ||||
| 
 | ||||
| function setTagFilter(state, tagFilter) { | ||||
| 	state.tagFilter = tagFilter; | ||||
| } | ||||
|  | @ -27,8 +19,6 @@ function setTheme(state, theme) { | |||
| } | ||||
| 
 | ||||
| export default { | ||||
| 	setNotifications, | ||||
| 	setUnseenNotificationsCount, | ||||
| 	setTagFilter, | ||||
| 	setRange, | ||||
| 	setBatch, | ||||
|  |  | |||
|  | @ -11,6 +11,4 @@ export default { | |||
| 	batch: storedBatch || 'all', | ||||
| 	sfw: storedSfw === 'true' || false, | ||||
| 	theme: storedTheme || deviceTheme, | ||||
| 	notifications: [], | ||||
| 	unseenNotificationsCount: 0, | ||||
| }; | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 5.1 MiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.0 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 30 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.6 MiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.9 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 36 KiB | 
|  | @ -2989,7 +2989,7 @@ const sites = [ | |||
| 	{ | ||||
| 		name: 'Black Ambush', | ||||
| 		slug: 'blackambush', | ||||
| 		alias: ['interracial', 'bbc'], | ||||
| 		tags: ['bbc'], | ||||
| 		url: 'https://blackambush.com', | ||||
| 		parent: 'exploitedx', | ||||
| 	}, | ||||
|  |  | |||
|  | @ -763,8 +763,9 @@ const tagMedia = [ | |||
| 	['dv-tp', 0, 'Luna Rival in SZ1490'], | ||||
| 	['facefucking', 5, 'Mia Moore B', 'throated'], | ||||
| 	['facefucking', 6, 'Halle Hayes in "Towering Temptress"', '5kporn'], | ||||
| 	['facefucking', 7, 'Anya Olsen and Audrey Snow in "Babysitter Busted Giving A BJ"', 'mommyblowsbest'], | ||||
| 	['facefucking', 'adria_rae_throated', 'Adria Rae in "Adria Rae Sucks Cock All Day"', 'throated'], | ||||
| 	['facefucking', 1, 'Paige Owens in "Dark Meat 12"', 'evilangel'], | ||||
| 	['facefucking', 7, 'Anya Olsen and Audrey Snow in "Babysitter Busted Giving A BJ"', 'mommyblowsbest'], | ||||
| 	['facefucking', 0, 'Ashly Anderson in "Rough Love"', 'hookuphotshot'], | ||||
| 	['facefucking', 2, 'Jynx Maze', 'throated'], | ||||
| 	['facefucking', 4, 'Brooklyn Gray in "Throats Fucks 6"', 'evilangel'], | ||||
|  | @ -793,7 +794,7 @@ const tagMedia = [ | |||
| 	['enhanced-boobs', '23d', 'Lulu Sex Bomb in "Tropical Touch"'], | ||||
| 	['enhanced-boobs', 22, 'Sakura Sena'], | ||||
| 	['enhanced-boobs', 'mareeva_trudy_photodromm_1', 'Mareeva and Trudy', 'photodromm'], | ||||
| 	['enhanced-boobs', 'lara_frost_legalporno', 'Lara Frost in NRX059', 'legalporno'], | ||||
| 	['enhanced-boobs', 'lara_frost_handsonhardcore', 'Lara Frost in "Handyman & Hubby Try To Satisfy Horny Little Ukrainian Nympho"', 'handsonhardcore'], | ||||
| 	['enhanced-boobs', 'shawna_lenee_inthecrack_3', 'Shawna Lenee', 'inthecrack'], | ||||
| 	['enhanced-boobs', 16, 'Marsha May in "Once You Go Black 7"', 'julesjordan'], | ||||
| 	['enhanced-boobs', 'azul_hermosa_pornstarslikeitbig', 'Azul Hermosa in "She Likes Rough Quickies"', 'pornstarslikeitbig'], | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue