123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- <template>
- <div>
- <div v-if="isReblog" class="card-header bg-light border-0" style="border-top-left-radius: 15px;border-top-right-radius: 15px;">
- <div class="media align-items-center" style="height:10px;">
- <a :href="reblogAccount.url" class="mx-2" @click.prevent="goToProfileById(reblogAccount.id)">
- <img :src="reblogAccount.avatar" style="border-radius:10px;" width="24" height="24" onerror="this.onerror=null;this.src='/storage/avatars/default.png?v=0';">
- </a>
- <div style="font-size:12px;font-weight:bold">
- <i class="far fa-retweet text-warning mr-1"></i> Reblogged by <a :href="reblogAccount.url" class="text-dark" @click.prevent="goToProfileById(reblogAccount.id)">@{{ reblogAccount.acct }}</a>
- </div>
- </div>
- </div>
- <div class="card-header border-0" style="border-top-left-radius: 15px;border-top-right-radius: 15px;">
- <div class="media align-items-center">
- <a :href="status.account.url" @click.prevent="goToProfile()" style="margin-right: 10px;">
- <img :src="getStatusAvatar()" style="border-radius:15px;" width="44" height="44" onerror="this.onerror=null;this.src='/storage/avatars/default.png?v=0';">
- </a>
- <div class="media-body">
- <p class="font-weight-bold username">
- <a :href="status.account.url" class="text-dark" :id="'apop_'+status.id" @click.prevent="goToProfile">
- {{ status.account.acct }}
- </a>
- <b-popover :target="'apop_'+status.id" triggers="hover" placement="bottom" custom-class="shadow border-0 rounded-px">
- <profile-hover-card
- :profile="status.account"
- v-on:follow="follow"
- v-on:unfollow="unfollow" />
- </b-popover>
- </p>
- <p class="text-lighter mb-0" style="font-size: 13px;">
- <span v-if="status.account.is_admin" class="d-none d-md-inline-block">
- <span class="badge badge-light text-danger user-select-none" title="Admin account">ADMIN</span>
- <span class="mx-1 text-lighter">·</span>
- </span>
- <a class="timestamp text-lighter" :href="status.url" @click.prevent="goToPost()" :title="status.created_at">
- {{ timeago(status.created_at) }}
- </a>
- <span v-if="config.ab.pue && status.hasOwnProperty('edited_at') && status.edited_at">
- <span class="mx-1 text-lighter">·</span>
- <a class="text-lighter" href="#" @click.prevent="openEditModal">Edited</a>
- </span>
- <span class="mx-1 text-lighter">·</span>
- <span class="visibility text-lighter" :title="scopeTitle(status.visibility)"><i :class="scopeIcon(status.visibility)"></i></span>
- <span v-if="status.place && status.place.hasOwnProperty('name')" class="d-none d-md-inline-block">
- <span class="mx-1 text-lighter">·</span>
- <span class="location text-lighter"><i class="far fa-map-marker-alt"></i> {{ status.place.name }}, {{ status.place.country }}</span>
- </span>
- </p>
- </div>
- <button v-if="!useDropdownMenu" class="btn btn-link text-lighter" @click="openMenu">
- <i class="far fa-ellipsis-v fa-lg"></i>
- </button>
- <b-dropdown
- v-else
- no-caret
- right
- variant="link"
- toggle-class="text-lighter"
- html="<i class='far fa-ellipsis-v fa-lg px-3'></i>"
- >
- <b-dropdown-item>
- <p class="mb-0 font-weight-bold">{{ $t('menu.viewPost') }}</p>
- </b-dropdown-item>
- <b-dropdown-item>
- <p class="mb-0 font-weight-bold">{{ $t('common.copyLink') }}</p>
- </b-dropdown-item>
- <b-dropdown-item v-if="status.local">
- <p class="mb-0 font-weight-bold">{{ $t('menu.embed') }}</p>
- </b-dropdown-item>
- <b-dropdown-divider v-if="!owner"></b-dropdown-divider>
- <b-dropdown-item v-if="!owner">
- <p class="mb-0 font-weight-bold">{{ $t('menu.report') }}</p>
- <p class="small text-muted mb-0">Report content that violate our rules</p>
- </b-dropdown-item>
- <b-dropdown-item v-if="!owner && status.hasOwnProperty('relationship')">
- <p class="mb-0 font-weight-bold">{{ status.relationship.muting ? 'Unmute' : 'Mute' }}</p>
- <p class="small text-muted mb-0">Hide posts from this account in your feeds</p>
- </b-dropdown-item>
- <b-dropdown-item v-if="!owner && status.hasOwnProperty('relationship')">
- <p class="mb-0 font-weight-bold text-danger">{{ status.relationship.blocking ? 'Unblock' : 'Block' }}</p>
- <p class="small text-muted mb-0">Restrict all content from this account</p>
- </b-dropdown-item>
- <b-dropdown-divider v-if="owner || admin"></b-dropdown-divider>
- <b-dropdown-item v-if="owner || admin">
- <p class="mb-0 font-weight-bold text-danger">
- {{ $t('common.delete') }}
- </p>
- </b-dropdown-item>
- </b-dropdown>
- </div>
- <edit-history-modal ref="editModal" :status="status" />
- </div>
- </div>
- </template>
- <script type="text/javascript">
- import ProfileHoverCard from './../profile/ProfileHoverCard.vue';
- import EditHistoryModal from './EditHistoryModal.vue';
- export default {
- props: {
- status: {
- type: Object
- },
- profile: {
- type: Object
- },
- useDropdownMenu: {
- type: Boolean,
- default: false
- },
- isReblog: {
- type: Boolean,
- default: false
- },
- reblogAccount: {
- type: Object
- }
- },
- components: {
- "profile-hover-card": ProfileHoverCard,
- "edit-history-modal": EditHistoryModal
- },
- data() {
- return {
- config: window.App.config,
- menuLoading: true,
- owner: false,
- admin: false,
- license: false
- }
- },
- methods: {
- timeago(ts) {
- let short = App.util.format.timeAgo(ts);
- if(
- short.endsWith('s') ||
- short.endsWith('m') ||
- short.endsWith('h')
- ) {
- return short;
- }
- const intl = new Intl.DateTimeFormat(undefined, {
- year: 'numeric',
- month: 'short',
- day: 'numeric',
- hour: 'numeric',
- minute: 'numeric'
- });
- return intl.format(new Date(ts));
- },
- openMenu() {
- this.$emit('menu');
- },
- scopeIcon(scope) {
- switch(scope) {
- case 'public':
- return 'far fa-globe';
- break;
- case 'unlisted':
- return 'far fa-lock-open';
- break;
- case 'private':
- return 'far fa-lock';
- break;
- default:
- return 'far fa-globe';
- break;
- }
- },
- scopeTitle(scope) {
- switch(scope) {
- case 'public':
- return 'Visible to everyone';
- break;
- case 'unlisted':
- return 'Hidden from public feeds';
- break;
- case 'private':
- return 'Only visible to followers';
- break;
- default:
- return '';
- break;
- }
- },
- goToPost() {
- if(location.pathname.split('/').pop() == this.status.id) {
- location.href = this.status.local ? this.status.url + '?fs=1' : this.status.url;
- return;
- }
- this.$router.push({
- name: 'post',
- path: `/i/web/post/${this.status.id}`,
- params: {
- id: this.status.id,
- cachedStatus: this.status,
- cachedProfile: this.profile
- }
- })
- },
- goToProfileById(id) {
- this.$nextTick(() => {
- this.$router.push({
- name: 'profile',
- path: `/i/web/profile/${id}`,
- params: {
- id: id,
- cachedUser: this.profile
- }
- });
- });
- },
- goToProfile() {
- this.$nextTick(() => {
- this.$router.push({
- name: 'profile',
- path: `/i/web/profile/${this.status.account.id}`,
- params: {
- id: this.status.account.id,
- cachedProfile: this.status.account,
- cachedUser: this.profile
- }
- });
- });
- },
- toggleContentWarning() {
- this.key++;
- this.sensitive = true;
- this.status.sensitive = !this.status.sensitive;
- },
- like() {
- event.currentTarget.blur();
- if(this.status.favourited) {
- this.$emit('unlike');
- } else {
- this.$emit('like');
- }
- },
- toggleMenu(bvEvent) {
- setTimeout(() => {
- this.menuLoading = false;
- }, 500);
- },
- closeMenu(bvEvent) {
- setTimeout(() => {
- bvEvent.target.parentNode.firstElementChild.blur();
- }, 100);
- },
- showLikes() {
- event.currentTarget.blur();
- this.$emit('likes-modal');
- },
- showShares() {
- event.currentTarget.blur();
- this.$emit('shares-modal');
- },
- showComments() {
- event.currentTarget.blur();
- this.showCommentDrawer = !this.showCommentDrawer;
- },
- copyLink() {
- event.currentTarget.blur();
- App.util.clipboard(this.status.url);
- },
- shareToOther() {
- if (navigator.canShare) {
- navigator.share({
- url: this.status.url
- })
- .then(() => console.log('Share was successful.'))
- .catch((error) => console.log('Sharing failed', error));
- } else {
- swal('Not supported', 'Your current device does not support native sharing.', 'error');
- }
- },
- counterChange(type) {
- this.$emit('counter-change', type);
- },
- showCommentLikes(post) {
- this.$emit('comment-likes-modal', post);
- },
- shareStatus() {
- this.$emit('share');
- },
- unshareStatus() {
- this.$emit('unshare');
- },
- handleReport(post) {
- this.$emit('handle-report', post);
- },
- follow() {
- this.$emit('follow');
- },
- unfollow() {
- this.$emit('unfollow');
- },
- handleReblog() {
- this.isReblogging = true;
- if(this.status.reblogged) {
- this.$emit('unshare');
- } else {
- this.$emit('share');
- }
- setTimeout(() => {
- this.isReblogging = false;
- }, 5000);
- },
- handleBookmark() {
- event.currentTarget.blur();
- this.isBookmarking = true;
- this.$emit('bookmark');
- setTimeout(() => {
- this.isBookmarking = false;
- }, 5000);
- },
- getStatusAvatar() {
- if(window._sharedData.user.id == this.status.account.id) {
- return window._sharedData.user.avatar;
- }
- return this.status.account.avatar;
- },
- openModTools() {
- this.$emit('mod-tools');
- },
- openEditModal() {
- this.$refs.editModal.open();
- }
- }
- }
- </script>
|