kopia lustrzana https://github.com/nextcloud/social
				
				
				
			Embedd timeline in profile page
Signed-off-by: Carl Schwan <carl@carlschwan.eu>pull/1469/head
							rodzic
							
								
									cb25fb1b4e
								
							
						
					
					
						commit
						fff26baedf
					
				|  | @ -37,11 +37,13 @@ use OCA\Social\Search\UnifiedSearchProvider; | ||||||
| use OCA\Social\Service\ConfigService; | use OCA\Social\Service\ConfigService; | ||||||
| use OCA\Social\Service\UpdateService; | use OCA\Social\Service\UpdateService; | ||||||
| use OCA\Social\WellKnown\WebfingerHandler; | use OCA\Social\WellKnown\WebfingerHandler; | ||||||
|  | use OCA\Social\Listeners\ProfileSectionListener; | ||||||
| use OCP\AppFramework\App; | use OCP\AppFramework\App; | ||||||
| use OCP\AppFramework\Bootstrap\IBootContext; | use OCP\AppFramework\Bootstrap\IBootContext; | ||||||
| use OCP\AppFramework\Bootstrap\IBootstrap; | use OCP\AppFramework\Bootstrap\IBootstrap; | ||||||
| use OCP\AppFramework\Bootstrap\IRegistrationContext; | use OCP\AppFramework\Bootstrap\IRegistrationContext; | ||||||
| use OCP\AppFramework\QueryException; | use OCP\AppFramework\QueryException; | ||||||
|  | use OCP\Profile\BeforeTemplateRenderedEvent; | ||||||
| use OCP\IDBConnection; | use OCP\IDBConnection; | ||||||
| use OCP\IServerContainer; | use OCP\IServerContainer; | ||||||
| use OC\DB\SchemaWrapper; | use OC\DB\SchemaWrapper; | ||||||
|  | @ -62,19 +64,12 @@ class Application extends App implements IBootstrap { | ||||||
| 		parent::__construct(self::APP_NAME, $params); | 		parent::__construct(self::APP_NAME, $params); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param IRegistrationContext $context |  | ||||||
| 	 */ |  | ||||||
| 	public function register(IRegistrationContext $context): void { | 	public function register(IRegistrationContext $context): void { | ||||||
| 		$context->registerSearchProvider(UnifiedSearchProvider::class); | 		$context->registerSearchProvider(UnifiedSearchProvider::class); | ||||||
| 		$context->registerWellKnownHandler(WebfingerHandler::class); | 		$context->registerWellKnownHandler(WebfingerHandler::class); | ||||||
|  | 		$context->registerEventListener(BeforeTemplateRenderedEvent::class, ProfileSectionListener::class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @param IBootContext $context |  | ||||||
| 	 */ |  | ||||||
| 	public function boot(IBootContext $context): void { | 	public function boot(IBootContext $context): void { | ||||||
| 		$manager = $context->getServerContainer() | 		$manager = $context->getServerContainer() | ||||||
| 						   ->getNotificationManager(); | 						   ->getNotificationManager(); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | <?php | ||||||
|  | declare(strict_types=1); | ||||||
|  | 
 | ||||||
|  | // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
 | ||||||
|  | // SPDX-License-Identifier: AGPL-3.0-or-later
 | ||||||
|  | 
 | ||||||
|  | namespace OCA\Social\Listeners; | ||||||
|  | 
 | ||||||
|  | use OCP\EventDispatcher\Event; | ||||||
|  | use OCP\EventDispatcher\IEventListener; | ||||||
|  | use OCP\Profile\BeforeTemplateRenderedEvent; | ||||||
|  | use OCP\Util; | ||||||
|  | 
 | ||||||
|  | class ProfileSectionListener implements IEventListener { | ||||||
|  | 	public function handle(Event $event): void { | ||||||
|  | 		if (!($event instanceof BeforeTemplateRenderedEvent)) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		Util::addScript('social', 'social-profilePage'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
| 				<span class="icon-boost" /> | 				<span class="icon-boost" /> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="boost"> | 			<div class="boost"> | ||||||
| 				<router-link v-if="item.actor_info" :to="{ name: 'profile', params: { account: item.local ? item.actor_info.preferredUsername : item.actor_info.account }}"> | 				<router-link v-if="!isProfilePage && item.actor_info" :to="{ name: 'profile', params: { account: item.local ? item.actor_info.preferredUsername : item.actor_info.account }}"> | ||||||
| 					<span v-tooltip.bottom="item.actor_info.account" class="post-author"> | 					<span v-tooltip.bottom="item.actor_info.account" class="post-author"> | ||||||
| 						{{ userDisplayName(item.actor_info) }} | 						{{ userDisplayName(item.actor_info) }} | ||||||
| 					</span> | 					</span> | ||||||
|  | @ -50,7 +50,14 @@ export default { | ||||||
| 		UserEntry | 		UserEntry | ||||||
| 	}, | 	}, | ||||||
| 	props: { | 	props: { | ||||||
| 		item: { type: Object, default: () => {} } | 		item: { | ||||||
|  | 			type: Object, | ||||||
|  | 			default: () => {} | ||||||
|  | 		}, | ||||||
|  | 		isProfilePage: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			default: false, | ||||||
|  | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	data() { | 	data() { | ||||||
| 		return { | 		return { | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| 		<div v-if="hasAttachments" class="post-attachments"> | 		<div v-if="hasAttachments" class="post-attachments"> | ||||||
| 			<post-attachment :attachments="item.attachment" /> | 			<post-attachment :attachments="item.attachment" /> | ||||||
| 		</div> | 		</div> | ||||||
| 		<div v-if="this.$route.params.type !== 'notifications' && !serverData.public" class="post-actions"> | 		<div v-if="this.$route && this.$route.params.type !== 'notifications' && !serverData.public" class="post-actions"> | ||||||
| 			<NcButton type="tertiary-no-background" | 			<NcButton type="tertiary-no-background" | ||||||
| 				v-tooltip="t('social', 'Reply')" | 				v-tooltip="t('social', 'Reply')" | ||||||
| 				@click="reply"> | 				@click="reply"> | ||||||
|  |  | ||||||
|  | @ -37,6 +37,9 @@ export default { | ||||||
| 		 * @property 		setup | 		 * @property 		setup | ||||||
| 		 */ | 		 */ | ||||||
| 		serverData() { | 		serverData() { | ||||||
|  | 			if (!this.$store) { | ||||||
|  | 				return {} | ||||||
|  | 			} | ||||||
| 			return this.$store.getters.getServerData | 			return this.$store.getters.getServerData | ||||||
| 		}, | 		}, | ||||||
| 		hostname() { | 		hostname() { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | // SPDX-FileCopyrigthText: 2022 Carl Schwan <carl@carlschwan.eu>
 | ||||||
|  | // SPDX-License-Identifier: AGPL-3.0-or-later
 | ||||||
|  | 
 | ||||||
|  | // eslint-disable-next-line
 | ||||||
|  | __webpack_nonce__ = btoa(OC.requestToken) | ||||||
|  | // eslint-disable-next-line
 | ||||||
|  | __webpack_public_path__ = OC.linkTo('social', 'js/') | ||||||
|  | 
 | ||||||
|  | import ProfilePageIntegration from './views/ProfilePageIntegration.vue'  | ||||||
|  | import Vue from 'vue' | ||||||
|  | import { sync } from 'vuex-router-sync' | ||||||
|  | 
 | ||||||
|  | if (!OCA?.Core?.ProfileSections) { | ||||||
|  | 	exit(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Vue.prototype.t = t | ||||||
|  | Vue.prototype.n = n | ||||||
|  | Vue.prototype.OC = OC | ||||||
|  | Vue.prototype.OCA = OCA | ||||||
|  | 
 | ||||||
|  | const View = Vue.extend(ProfilePageIntegration) | ||||||
|  | 
 | ||||||
|  | OCA.Core.ProfileSections.registerSection((el, userId) => { | ||||||
|  | 	return View | ||||||
|  | }) | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | <template> | ||||||
|  | 	<div> | ||||||
|  | 		<h2>Social</h2> | ||||||
|  | 		<transition-group name="list" tag="div"> | ||||||
|  | 			<TimelineEntry v-for="entry in timeline" :key="entry.id" :item="entry" :isProfilePage="true" /> | ||||||
|  | 		</transition-group> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | import ProfileInfo from './../components/ProfileInfo.vue' | ||||||
|  | import TimelineEntry from './../components/TimelineEntry.vue' | ||||||
|  | import axios from '@nextcloud/axios' | ||||||
|  | import { generateUrl } from '@nextcloud/router' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  | 	name: 'ProfilePageIntegration', | ||||||
|  | 	props: { | ||||||
|  | 		userId: { | ||||||
|  | 			type: String, | ||||||
|  | 			default: '', | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			accountInfo: null, | ||||||
|  | 			timeline: [], | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	components: { | ||||||
|  | 		ProfileInfo, | ||||||
|  | 		TimelineEntry, | ||||||
|  | 	}, | ||||||
|  | 	computed: { | ||||||
|  | 		getCount() { | ||||||
|  | 			let account = this.accountInfo | ||||||
|  | 			return (field) => account.details.count ? account.details.count[field] : '' | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	// Start fetching account information before mounting the component | ||||||
|  | 	beforeMount() { | ||||||
|  | 		let fetchMethod = 'fetchPublicAccountInfo' | ||||||
|  | 
 | ||||||
|  | 		let uid = this.userId | ||||||
|  | 
 | ||||||
|  | 		axios.get(generateUrl(`apps/social/api/v1/account/${uid}/info`)).then((response) => { | ||||||
|  | 			this.accountInfo = response.data.result.account | ||||||
|  | 			console.log(this.accountInfo) | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		const since = Math.floor(Date.now() / 1000) + 1 | ||||||
|  | 
 | ||||||
|  | 		axios.get(generateUrl(`apps/social/api/v1/account/${uid}/stream?limit=25&since=${since}`)).then(({ data }) => { | ||||||
|  | 			console.log(this.timeline) | ||||||
|  | 			this.timeline = data.result | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | @ -7,6 +7,7 @@ const webpackConfig = require('@nextcloud/webpack-vue-config') | ||||||
| webpackConfig.entry = { | webpackConfig.entry = { | ||||||
| 	social: path.join(__dirname, 'src', 'main.js'), | 	social: path.join(__dirname, 'src', 'main.js'), | ||||||
| 	ostatus: path.join(__dirname, 'src', 'ostatus.js'), | 	ostatus: path.join(__dirname, 'src', 'ostatus.js'), | ||||||
|  | 	profilePage: path.join(__dirname, 'src', 'profile.js'), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = webpackConfig | module.exports = webpackConfig | ||||||
|  |  | ||||||
		Ładowanie…
	
		Reference in New Issue
	
	 Carl Schwan
						Carl Schwan