Profile.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <template>
  2. <div class="profile-timeline-component">
  3. <div v-if="isLoaded" class="container-fluid mt-3">
  4. <div v-if="profile && profile.hasOwnProperty('moved') && profile.moved.hasOwnProperty('id') && !showMoved">
  5. <div class="row justify-content-center">
  6. <div class="col-12 col-md-6">
  7. <div class="card shadow-none border card-body mt-5 mb-3 ft-std" style="border-radius: 20px;">
  8. <p class="lead font-weight-bold text-center mb-0"><i class="far fa-exclamation-triangle mr-2"></i>This account has indicated their new account is:</p>
  9. </div>
  10. <div class="card shadow-none border" style="border-radius: 20px;">
  11. <div class="card-body ft-std">
  12. <div class="d-flex justify-content-between align-items-center" style="gap: 1rem;">
  13. <div class="d-flex align-items-center flex-shrink-1" style="gap: 1rem;">
  14. <img :src="profile.moved.avatar" width="50" height="50" class="rounded-circle">
  15. <p class="h3 font-weight-light mb-0 text-break">&commat;{{ profile.moved.acct }}</p>
  16. </div>
  17. <div class="d-flex flex-grow-1 justify-content-end" style="min-width: 200px;">
  18. <router-link
  19. :to="`/i/web/profile/${profile.moved.id}`"
  20. class="btn btn-outline-primary rounded-pill font-weight-bold"
  21. >View New Account</router-link>
  22. </div>
  23. </div>
  24. </div>
  25. </div>
  26. <hr>
  27. <p class="lead text-center ft-std">
  28. <a
  29. href="#"
  30. class="btn btn-primary btn-lg rounded-pill font-weight-bold px-5"
  31. @click.prevent="showMoved = true">Proceed</a>
  32. </p>
  33. </div>
  34. </div>
  35. </div>
  36. <div v-else class="row">
  37. <div class="col-md-3 d-md-block px-md-3 px-xl-5">
  38. <profile-sidebar
  39. :profile="profile"
  40. :relationship="relationship"
  41. :user="curUser"
  42. v-on:back="goBack"
  43. v-on:toggletab="toggleTab"
  44. v-on:updateRelationship="updateRelationship"
  45. @follow="follow"
  46. @unfollow="unfollow" />
  47. </div>
  48. <div class="col-md-8 px-md-5">
  49. <component
  50. v-bind:is="getTabComponentName()"
  51. :key="getTabComponentName() + profile.id"
  52. :profile="profile"
  53. :relationship="relationship" />
  54. </div>
  55. </div>
  56. <drawer />
  57. </div>
  58. </div>
  59. </template>
  60. <script type="text/javascript">
  61. import Drawer from './partials/drawer.vue';
  62. import ProfileFeed from './partials/profile/ProfileFeed.vue';
  63. import ProfileSidebar from './partials/profile/ProfileSidebar.vue';
  64. import ProfileFollowers from './partials/profile/ProfileFollowers.vue';
  65. import ProfileFollowing from './partials/profile/ProfileFollowing.vue';
  66. export default {
  67. props: {
  68. id: {
  69. type: String
  70. },
  71. profileId: {
  72. type: String
  73. },
  74. username: {
  75. type: String
  76. },
  77. cachedProfile: {
  78. type: Object
  79. },
  80. cachedUser: {
  81. type: Object
  82. }
  83. },
  84. components: {
  85. "drawer": Drawer,
  86. "profile-feed": ProfileFeed,
  87. "profile-sidebar": ProfileSidebar,
  88. "profile-followers": ProfileFollowers,
  89. "profile-following": ProfileFollowing
  90. },
  91. data() {
  92. return {
  93. isLoaded: false,
  94. curUser: undefined,
  95. tab: "index",
  96. profile: undefined,
  97. relationship: undefined,
  98. showMoved: false,
  99. }
  100. },
  101. mounted() {
  102. this.init();
  103. },
  104. watch: {
  105. '$route': 'init'
  106. },
  107. methods: {
  108. init() {
  109. this.tab = 'index';
  110. this.isLoaded = false;
  111. this.relationship = undefined;
  112. this.owner = false;
  113. if(this.cachedProfile && this.cachedUser) {
  114. this.curUser = this.cachedUser;
  115. this.profile = this.cachedProfile;
  116. // this.fetchPosts();
  117. // this.isLoaded = true;
  118. this.fetchRelationship();
  119. if(this.cachedProfile && this.cachedProfile.local) {
  120. window.history.pushState({}, '', `/${this.cachedProfile.acct}`);
  121. }
  122. } else {
  123. this.curUser = window._sharedData.user;
  124. this.fetchProfile();
  125. }
  126. },
  127. getTabComponentName() {
  128. switch(this.tab) {
  129. case 'index':
  130. return "profile-feed";
  131. break;
  132. default:
  133. return `profile-${this.tab}`;
  134. break;
  135. }
  136. },
  137. fetchProfile() {
  138. let id = this.profileId ? this.profileId : this.id;
  139. axios.get('/api/pixelfed/v1/accounts/' + id)
  140. .then(res => {
  141. this.profile = res.data;
  142. if(res.data.id == this.curUser.id) {
  143. this.owner = true;
  144. // this.isLoaded = true;
  145. // this.loaded();
  146. // this.fetchPosts();
  147. this.fetchRelationship();
  148. } else {
  149. this.owner = false;
  150. this.fetchRelationship();
  151. }
  152. if(res.data && res.data.local) {
  153. window.history.pushState({}, '', `/${res.data.acct}`);
  154. }
  155. })
  156. .catch(err => {
  157. this.$router.push('/i/web/404');
  158. });
  159. },
  160. fetchRelationship() {
  161. if(this.owner) {
  162. this.relationship = {};
  163. this.isLoaded = true;
  164. return;
  165. }
  166. axios.get('/api/v1/accounts/relationships', {
  167. params: {
  168. 'id[]': this.profile.id
  169. }
  170. }).then(res => {
  171. this.relationship = res.data[0];
  172. this.isLoaded = true;
  173. })
  174. },
  175. toggleTab(tab) {
  176. this.tab = tab;
  177. },
  178. goBack() {
  179. this.$router.go(-1);
  180. },
  181. unfollow() {
  182. axios.post('/api/v1/accounts/' + this.profile.id + '/unfollow')
  183. .then(res => {
  184. this.$store.commit('updateRelationship', [res.data])
  185. this.relationship = res.data;
  186. if(this.profile.locked) {
  187. location.reload();
  188. }
  189. this.profile.followers_count--;
  190. }).catch(err => {
  191. swal('Oops!', 'An error occured when attempting to unfollow this account.', 'error');
  192. this.relationship.following = true;
  193. });
  194. },
  195. follow() {
  196. axios.post('/api/v1/accounts/' + this.profile.id + '/follow')
  197. .then(res => {
  198. this.$store.commit('updateRelationship', [res.data])
  199. this.relationship = res.data;
  200. if(this.profile.locked) {
  201. this.relationship.requested = true;
  202. }
  203. this.profile.followers_count++;
  204. }).catch(err => {
  205. swal('Oops!', 'An error occured when attempting to follow this account.', 'error');
  206. this.relationship.following = false;
  207. });
  208. },
  209. updateRelationship(val) {
  210. this.relationship = val;
  211. }
  212. }
  213. }
  214. </script>
  215. <style lang="scss" scoped>
  216. .profile-timeline-component {
  217. margin-bottom: 10rem;
  218. }
  219. </style>