mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-10-26 19:14:12 +00:00 
			
		
		
		
	✌️
This commit is contained in:
		
							parent
							
								
									8a8d97b8c7
								
							
						
					
					
						commit
						4953842ff1
					
				
					 9 changed files with 165 additions and 25 deletions
				
			
		|  | @ -98,7 +98,9 @@ common/views/components/nav.vue: | |||
|   feedback: "Feedback" | ||||
| 
 | ||||
| common/views/components/note-menu.vue: | ||||
|   favorite: "Favorite this note" | ||||
|   pin: "Pin to profile page" | ||||
|   remote: "Show on origin" | ||||
| 
 | ||||
| common/views/components/poll.vue: | ||||
|   vote-to: "Vote for '{}'" | ||||
|  |  | |||
|  | @ -98,7 +98,9 @@ common/views/components/nav.vue: | |||
|   feedback: "フィードバック" | ||||
| 
 | ||||
| common/views/components/note-menu.vue: | ||||
|   favorite: "Favorite this note" | ||||
|   pin: "Épingler sur votre profile" | ||||
|   remote: "投稿元で見る" | ||||
| 
 | ||||
| common/views/components/poll.vue: | ||||
|   vote-to: "Voter pour '{}'" | ||||
|  |  | |||
|  | @ -98,7 +98,9 @@ common/views/components/nav.vue: | |||
|   feedback: "フィードバック" | ||||
| 
 | ||||
| common/views/components/note-menu.vue: | ||||
|   favorite: "お気に入り" | ||||
|   pin: "ピン留め" | ||||
|   remote: "投稿元で見る" | ||||
| 
 | ||||
| common/views/components/poll.vue: | ||||
|   vote-to: "「{}」に投票する" | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| <div class="mk-note-menu"> | ||||
| 	<div class="backdrop" ref="backdrop" @click="close"></div> | ||||
| 	<div class="popover" :class="{ compact }" ref="popover"> | ||||
| 		<button @click="favorite">%i18n:@favorite%</button> | ||||
| 		<button v-if="note.userId == os.i.id" @click="pin">%i18n:@pin%</button> | ||||
| 		<a v-if="note.uri" :href="note.uri" target="_blank">%i18n:@remote%</a> | ||||
| 	</div> | ||||
|  | @ -58,6 +59,14 @@ export default Vue.extend({ | |||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		favorite() { | ||||
| 			(this as any).api('notes/favorites/create', { | ||||
| 				noteId: this.note.id | ||||
| 			}).then(() => { | ||||
| 				this.$destroy(); | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		close() { | ||||
| 			(this.$refs.backdrop as any).style.pointerEvents = 'none'; | ||||
| 			anime({ | ||||
|  | @ -142,6 +151,7 @@ $border-color = rgba(27, 31, 35, 0.15) | |||
| 		> a | ||||
| 			display block | ||||
| 			padding 8px 16px | ||||
| 			width 100% | ||||
| 
 | ||||
| 			&:hover | ||||
| 				color $theme-color-foreground | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ import updateBanner from './api/update-banner'; | |||
| 
 | ||||
| import MkIndex from './views/pages/index.vue'; | ||||
| import MkUser from './views/pages/user/user.vue'; | ||||
| import MkFavorites from './views/pages/favorites.vue'; | ||||
| import MkSelectDrive from './views/pages/selectdrive.vue'; | ||||
| import MkDrive from './views/pages/drive.vue'; | ||||
| import MkHomeCustomize from './views/pages/home-customize.vue'; | ||||
|  | @ -50,6 +51,7 @@ init(async (launch) => { | |||
| 		routes: [ | ||||
| 			{ path: '/', name: 'index', component: MkIndex }, | ||||
| 			{ path: '/i/customize-home', component: MkHomeCustomize }, | ||||
| 			{ path: '/i/favorites', component: MkFavorites }, | ||||
| 			{ path: '/i/messaging/:user', component: MkMessagingRoom }, | ||||
| 			{ path: '/i/drive', component: MkDrive }, | ||||
| 			{ path: '/i/drive/folder/:folder', component: MkDrive }, | ||||
|  |  | |||
							
								
								
									
										73
									
								
								src/client/app/desktop/views/pages/favorites.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/client/app/desktop/views/pages/favorites.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| <template> | ||||
| <mk-ui> | ||||
| 	<main v-if="!fetching"> | ||||
| 		<template v-for="favorite in favorites"> | ||||
| 			<mk-note-detail :note="favorite.note" :key="favorite.note.id"/> | ||||
| 		</template> | ||||
| 		<a v-if="existMore" @click="more">さらに読み込む</a> | ||||
| 	</main> | ||||
| </mk-ui> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import Progress from '../../../common/scripts/loading'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	data() { | ||||
| 		return { | ||||
| 			fetching: true, | ||||
| 			favorites: [], | ||||
| 			existMore: false, | ||||
| 			moreFetching: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	created() { | ||||
| 		this.fetch(); | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		fetch() { | ||||
| 			Progress.start(); | ||||
| 			this.fetching = true; | ||||
| 
 | ||||
| 			(this as any).api('i/favorites', { | ||||
| 				limit: 11 | ||||
| 			}).then(favorites => { | ||||
| 				if (favorites.length == 11) { | ||||
| 					this.existMore = true; | ||||
| 					favorites.pop(); | ||||
| 				} | ||||
| 
 | ||||
| 				this.favorites = favorites; | ||||
| 				this.fetching = false; | ||||
| 
 | ||||
| 				Progress.done(); | ||||
| 			}); | ||||
| 		}, | ||||
| 		more() { | ||||
| 			this.moreFetching = true; | ||||
| 			(this as any).api('i/favorites', { | ||||
| 				limit: 11, | ||||
| 				maxId: this.favorites[this.favorites.length - 1].id | ||||
| 			}).then(favorites => { | ||||
| 				if (favorites.length == 11) { | ||||
| 					this.existMore = true; | ||||
| 					favorites.pop(); | ||||
| 				} else { | ||||
| 					this.existMore = false; | ||||
| 				} | ||||
| 
 | ||||
| 				this.favorites = this.favorites.concat(favorites); | ||||
| 				this.moreFetching = false; | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="stylus" scoped> | ||||
| main | ||||
| 	margin 0 auto | ||||
| 	padding 16px | ||||
| 	max-width 700px | ||||
| </style> | ||||
|  | @ -1,5 +1,7 @@ | |||
| import * as mongo from 'mongodb'; | ||||
| import deepcopy = require('deepcopy'); | ||||
| import db from '../db/mongodb'; | ||||
| import { pack as packNote } from './note'; | ||||
| 
 | ||||
| const Favorite = db.get<IFavorite>('favorites'); | ||||
| Favorite.createIndex(['userId', 'noteId'], { unique: true }); | ||||
|  | @ -38,3 +40,35 @@ export async function deleteFavorite(favorite: string | mongo.ObjectID | IFavori | |||
| 		_id: f._id | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Pack a favorite for API response | ||||
|  */ | ||||
| export const pack = ( | ||||
| 	favorite: any, | ||||
| 	me: any | ||||
| ) => new Promise<any>(async (resolve, reject) => { | ||||
| 	let _favorite: any; | ||||
| 
 | ||||
| 	// Populate the favorite if 'favorite' is ID
 | ||||
| 	if (mongo.ObjectID.prototype.isPrototypeOf(favorite)) { | ||||
| 		_favorite = await Favorite.findOne({ | ||||
| 			_id: favorite | ||||
| 		}); | ||||
| 	} else if (typeof favorite === 'string') { | ||||
| 		_favorite = await Favorite.findOne({ | ||||
| 			_id: new mongo.ObjectID(favorite) | ||||
| 		}); | ||||
| 	} else { | ||||
| 		_favorite = deepcopy(favorite); | ||||
| 	} | ||||
| 
 | ||||
| 	// Rename _id to id
 | ||||
| 	_favorite.id = _favorite._id; | ||||
| 	delete _favorite._id; | ||||
| 
 | ||||
| 	// Populate note
 | ||||
| 	_favorite.note = await packNote(_favorite.noteId, me); | ||||
| 
 | ||||
| 	resolve(_favorite); | ||||
| }); | ||||
|  |  | |||
|  | @ -233,6 +233,12 @@ const endpoints: Endpoint[] = [ | |||
| 		kind: 'notification-read' | ||||
| 	}, | ||||
| 
 | ||||
| 	{ | ||||
| 		name: 'i/favorites', | ||||
| 		withCredential: true, | ||||
| 		kind: 'favorites-read' | ||||
| 	}, | ||||
| 
 | ||||
| 	{ | ||||
| 		name: 'othello/match', | ||||
| 		withCredential: true | ||||
|  |  | |||
|  | @ -2,43 +2,52 @@ | |||
|  * Module dependencies | ||||
|  */ | ||||
| import $ from 'cafy'; | ||||
| import Favorite from '../../../../models/favorite'; | ||||
| import { pack } from '../../../../models/note'; | ||||
| import Favorite, { pack } from '../../../../models/favorite'; | ||||
| 
 | ||||
| /** | ||||
|  * Get followers of a user | ||||
|  * | ||||
|  * @param {any} params | ||||
|  * @param {any} user | ||||
|  * @return {Promise<any>} | ||||
|  * Get favorited notes | ||||
|  */ | ||||
| module.exports = (params, user) => new Promise(async (res, rej) => { | ||||
| 	// Get 'limit' parameter
 | ||||
| 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; | ||||
| 	if (limitErr) return rej('invalid limit param'); | ||||
| 
 | ||||
| 	// Get 'offset' parameter
 | ||||
| 	const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$; | ||||
| 	if (offsetErr) return rej('invalid offset param'); | ||||
| 	// Get 'sinceId' parameter
 | ||||
| 	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$; | ||||
| 	if (sinceIdErr) return rej('invalid sinceId param'); | ||||
| 
 | ||||
| 	// Get 'sort' parameter
 | ||||
| 	const [sort = 'desc', sortError] = $(params.sort).optional.string().or('desc asc').$; | ||||
| 	if (sortError) return rej('invalid sort param'); | ||||
| 	// Get 'untilId' parameter
 | ||||
| 	const [untilId, untilIdErr] = $(params.untilId).optional.id().$; | ||||
| 	if (untilIdErr) return rej('invalid untilId param'); | ||||
| 
 | ||||
| 	// Check if both of sinceId and untilId is specified
 | ||||
| 	if (sinceId && untilId) { | ||||
| 		return rej('cannot set sinceId and untilId'); | ||||
| 	} | ||||
| 
 | ||||
| 	const query = { | ||||
| 		userId: user._id | ||||
| 	} as any; | ||||
| 
 | ||||
| 	const sort = { | ||||
| 		_id: -1 | ||||
| 	}; | ||||
| 
 | ||||
| 	if (sinceId) { | ||||
| 		sort._id = 1; | ||||
| 		query._id = { | ||||
| 			$gt: sinceId | ||||
| 		}; | ||||
| 	} else if (untilId) { | ||||
| 		query._id = { | ||||
| 			$lt: untilId | ||||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	// Get favorites
 | ||||
| 	const favorites = await Favorite | ||||
| 		.find({ | ||||
| 			userId: user._id | ||||
| 		}, { | ||||
| 			limit: limit, | ||||
| 			skip: offset, | ||||
| 			sort: { | ||||
| 				_id: sort == 'asc' ? 1 : -1 | ||||
| 			} | ||||
| 		}); | ||||
| 		.find(query, { limit, sort }); | ||||
| 
 | ||||
| 	// Serialize
 | ||||
| 	res(await Promise.all(favorites.map(async favorite => | ||||
| 		await pack(favorite.noteId) | ||||
| 	))); | ||||
| 	res(await Promise.all(favorites.map(favorite => pack(favorite, user)))); | ||||
| }); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue