123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template>
- <div>
- <b-modal
- ref="sharesModal"
- centered
- size="md"
- :scrollable="true"
- hide-footer
- header-class="py-2"
- body-class="p-0"
- title-class="w-100 text-center pl-4 font-weight-bold"
- title-tag="p"
- title="Shared By">
- <div v-if="isLoading" class="likes-loader list-group border-top-0" style="max-height: 500px;">
- <like-placeholder />
- </div>
- <div v-else>
- <div v-if="!likes.length" class="d-flex justify-content-center align-items-center" style="height: 140px;">
- <p class="font-weight-bold mb-0">Nobody has shared this yet!</p>
- </div>
- <div v-else class="list-group" style="max-height: 500px;">
- <div v-for="(account, index) in likes" class="list-group-item border-left-0 border-right-0 px-3" :class="[ index === 0 ? 'border-top-0' : '']">
- <div class="media align-items-center">
- <img :src="account.avatar" width="40" height="40" style="border-radius: 8px;" class="mr-3 shadow-sm" onerror="this.src='/storage/avatars/default.jpg?v=0';this.onerror=null;">
- <div class="media-body">
- <p class="mb-0 text-truncate"><a :href="account.url" class="text-dark font-weight-bold text-decoration-none" @click.prevent="goToProfile(account)">{{ getUsername(account) }}</a></p>
- <p class="mb-0 mt-n1 text-dark font-weight-bold small text-break">@{{ account.acct }}</p>
- </div>
- <div>
- <button
- v-if="account.id == user.id"
- class="btn btn-outline-muted rounded-pill btn-sm font-weight-bold"
- @click="goToProfile(profile)"
- style="width:110px;">
- View Profile
- </button>
- <button
- v-else-if="account.follows"
- class="btn btn-outline-muted rounded-pill btn-sm font-weight-bold"
- :disabled="isUpdatingFollowState"
- @click="handleUnfollow(index)"
- style="width:110px;">
- <span v-if="isUpdatingFollowState && followStateIndex === index">
- <b-spinner small />
- </span>
- <span v-else>Following</span>
- </button>
- <button
- v-else-if="!account.follows"
- class="btn btn-primary rounded-pill btn-sm font-weight-bold"
- :disabled="isUpdatingFollowState"
- @click="handleFollow(index)"
- style="width:110px;">
- <span v-if="isUpdatingFollowState && followStateIndex === index">
- <b-spinner small />
- </span>
- <span v-else>Follow</span>
- </button>
- </div>
- </div>
- </div>
- <div v-if="canLoadMore">
- <intersect @enter="enterIntersect">
- <like-placeholder class="border-top-0" />
- </intersect>
- <like-placeholder />
- </div>
- </div>
- </div>
- </b-modal>
- </div>
- </template>
- <script type="text/javascript">
- import Intersect from 'vue-intersect'
- import LikePlaceholder from './LikeListPlaceholder.vue';
- import { parseLinkHeader } from '@web3-storage/parse-link-header';
- export default {
- props: {
- status: {
- type: Object
- },
- profile: {
- type: Object
- }
- },
- components: {
- "intersect": Intersect,
- "like-placeholder": LikePlaceholder
- },
- data() {
- return {
- isOpen: false,
- isLoading: true,
- canLoadMore: false,
- isFetchingMore: false,
- likes: [],
- ids: [],
- cursor: undefined,
- isUpdatingFollowState: false,
- followStateIndex: undefined,
- user: window._sharedData.user
- }
- },
- methods: {
- clear() {
- this.isOpen = false;
- this.isLoading = true;
- this.canLoadMore = false;
- this.isFetchingMore = false;
- this.likes = [];
- this.ids = [];
- this.cursor = undefined;
- },
- fetchShares() {
- axios.get('/api/v1/statuses/'+this.status.id+'/reblogged_by', {
- params: {
- limit: 40,
- '_pe': 1
- }
- })
- .then(res => {
- this.ids = res.data.map(a => a.id);
- this.likes = res.data;
- if(res.headers && res.headers.link) {
- const links = parseLinkHeader(res.headers.link);
- if(links.prev) {
- this.cursor = links.prev.cursor;
- this.canLoadMore = true;
- } else {
- this.canLoadMore = false;
- }
- } else {
- this.canLoadMore = false;
- }
- this.isLoading = false;
- });
- },
- open() {
- if(this.cursor) {
- this.clear();
- }
- this.isOpen = true;
- this.fetchShares();
- this.$refs.sharesModal.show();
- },
- enterIntersect() {
- if(this.isFetchingMore) {
- return;
- }
- this.isFetchingMore = true;
- axios.get('/api/v1/statuses/'+this.status.id+'/reblogged_by', {
- params: {
- limit: 10,
- cursor: this.cursor,
- '_pe': 1
- }
- }).then(res => {
- if(!res.data || !res.data.length) {
- this.canLoadMore = false;
- this.isFetchingMore = false;
- return;
- }
- res.data.forEach(user => {
- if(this.ids.indexOf(user.id) == -1) {
- this.ids.push(user.id);
- this.likes.push(user);
- }
- })
- if(res.headers && res.headers.link) {
- const links = parseLinkHeader(res.headers.link);
- if(links.prev) {
- this.cursor = links.prev.cursor;
- } else {
- this.canLoadMore = false;
- }
- } else {
- this.canLoadMore = false;
- }
- this.isFetchingMore = false;
- })
- },
- getUsername(account) {
- return account.display_name ? account.display_name : account.username;
- },
- goToProfile(account) {
- this.$router.push({
- name: 'profile',
- path: `/i/web/profile/${account.id}`,
- params: {
- id: account.id,
- cachedProfile: account,
- cachedUser: this.profile
- }
- })
- },
- handleFollow(index) {
- event.currentTarget.blur();
- this.followStateIndex = index;
- this.isUpdatingFollowState = true;
- let account = this.likes[index];
- axios.post('/api/v1/accounts/' + account.id + '/follow')
- .then(res => {
- this.likes[index].follows = true;
- this.followStateIndex = undefined;
- this.isUpdatingFollowState = false;
- });
- },
- handleUnfollow(index) {
- event.currentTarget.blur();
- this.followStateIndex = index;
- this.isUpdatingFollowState = true;
- let account = this.likes[index];
- axios.post('/api/v1/accounts/' + account.id + '/unfollow')
- .then(res => {
- this.likes[index].follows = false;
- this.followStateIndex = undefined;
- this.isUpdatingFollowState = false;
- });
- }
- }
- }
- </script>
|