StoryCarousel.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <template>
  2. <div class="story-carousel-component">
  3. <div v-if="canShow" class="d-flex story-carousel-component-wrapper" style="overflow-y: auto;z-index: 3;">
  4. <a class="col-4 col-lg-3 col-xl-2 px-1 text-dark text-decoration-none" href="/i/stories/new" style="max-width: 120px;">
  5. <template v-if="selfStory && selfStory.length">
  6. <div
  7. class="story-wrapper text-white shadow-sm mb-3"
  8. :style="{ background: `linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.4)), url(${selfStory[0].latest.preview_url})`, backgroundSize: 'cover', backgroundPosition: 'center'}"
  9. style="width: 100%;height:200px;border-radius:15px;">
  10. <div class="story-wrapper-blur d-flex flex-column align-items-center justify-content-between" style="display: block;width: 100%;height:100%;">
  11. <p class="mb-4"></p>
  12. <p class="mb-0"><i class="fal fa-plus-circle fa-2x"></i></p>
  13. <p class="font-weight-bold">My Story</p>
  14. </div>
  15. </div>
  16. </template>
  17. <template v-else>
  18. <div
  19. class="story-wrapper text-white shadow-sm d-flex flex-column align-items-center justify-content-between"
  20. style="width: 100%;height:200px;border-radius:15px;">
  21. <p class="mb-4"></p>
  22. <p class="mb-0"><i class="fal fa-plus-circle fa-2x"></i></p>
  23. <p class="font-weight-bold">{{ $t('story.add') }}</p>
  24. </div>
  25. </template>
  26. </a>
  27. <div v-for="(story, index) in stories" class="col-4 col-lg-3 col-xl-2 px-1" style="max-width: 120px;">
  28. <template v-if="story.hasOwnProperty('url')">
  29. <a class="story" :href="story.url">
  30. <div
  31. v-if="story.latest && story.latest.type == 'photo'"
  32. class="shadow-sm story-wrapper"
  33. :class="{ seen: story.seen }"
  34. :style="{ background: `linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.4)), url(${story.latest.preview_url})`, backgroundSize: 'cover', backgroundPosition: 'center'}">
  35. <div class="story-wrapper-blur" style="display: block;width: 100%;height:100%;position:relative;">
  36. <div class="px-2" style="display: block;width: 100%;bottom:0;position: absolute;">
  37. <p class="mt-3 mb-0">
  38. <img :src="story.avatar" width="30" height="30" class="avatar" draggable="false" onerror="this.onerror=null;this.src='/storage/avatars/default.jpg?v=0';">
  39. </p>
  40. <p class="mb-0"></p>
  41. <p class="username font-weight-bold small text-truncate">
  42. {{ story.username }}
  43. </p>
  44. </div>
  45. </div>
  46. </div>
  47. <div
  48. v-else
  49. class="shadow-sm story-wrapper">
  50. <div class="px-2" style="display: block;width: 100%;bottom:0;position: absolute;">
  51. <p class="mt-3 mb-0">
  52. <img :src="story.avatar" width="30" height="30" class="avatar">
  53. </p>
  54. <p class="mb-0"></p>
  55. <p class="username font-weight-bold small text-truncate">
  56. {{ story.username }}
  57. </p>
  58. </div>
  59. </div>
  60. </a>
  61. </template>
  62. <template v-else>
  63. <div
  64. class="story shadow-sm story-wrapper seen"
  65. :style="{ background: `linear-gradient(rgba(0,0,0,0.01),rgba(0,0,0,0.04))`}">
  66. <div class="story-wrapper-blur" style="display: block;width: 100%;height:100%;position:relative;">
  67. <div class="px-2" style="display: block;width: 100%;bottom:0;position: absolute;">
  68. <p class="mt-3 mb-0">
  69. </p>
  70. <p class="mb-0"></p>
  71. <p class="username font-weight-bold small text-truncate">
  72. </p>
  73. </div>
  74. </div>
  75. </div>
  76. </template>
  77. </div>
  78. <template v-if="selfStory && selfStory.length && stories.length < 2">
  79. <div v-for="i in 5" class="col-4 col-lg-3 col-xl-2 px-1 story" style="max-width: 120px;">
  80. <div
  81. class="shadow-sm story-wrapper seen"
  82. :style="{ background: `linear-gradient(rgba(0,0,0,0.01),rgba(0,0,0,0.04))`}">
  83. <div class="story-wrapper-blur" style="display: block;width: 100%;height:100%;position:relative;">
  84. <div class="px-2" style="display: block;width: 100%;bottom:0;position: absolute;">
  85. <p class="mt-3 mb-0">
  86. </p>
  87. <p class="mb-0"></p>
  88. <p class="username font-weight-bold small text-truncate">
  89. </p>
  90. </div>
  91. </div>
  92. </div>
  93. </div>
  94. </template>
  95. </div>
  96. </div>
  97. </template>
  98. <script type="text/javascript">
  99. export default {
  100. props: {
  101. profile: {
  102. type: Object
  103. }
  104. },
  105. data() {
  106. return {
  107. canShow: false,
  108. stories: [],
  109. selfStory: undefined
  110. }
  111. },
  112. mounted() {
  113. this.fetchStories();
  114. },
  115. methods: {
  116. fetchStories() {
  117. axios.get('/api/web/stories/v1/recent')
  118. .then(res => {
  119. if(res.data && res.data.length) {
  120. this.selfStory = res.data.filter(s => s.pid == this.profile.id);
  121. let activeStories = res.data.filter(s => s.pid !== this.profile.id);
  122. this.stories = activeStories;
  123. this.canShow = true;
  124. if(!activeStories || !activeStories.length || activeStories.length < 5) {
  125. this.stories.push(...Array(5 - activeStories.length).keys())
  126. }
  127. }
  128. })
  129. }
  130. }
  131. }
  132. </script>
  133. <style lang="scss">
  134. .story-carousel-component {
  135. &-wrapper {
  136. -ms-overflow-style: none;
  137. scrollbar-width: none;
  138. &::-webkit-scrollbar {
  139. width: 0 !important
  140. }
  141. }
  142. .story {
  143. &-wrapper {
  144. display: block;
  145. position: relative;
  146. width: 100%;
  147. height: 200px;
  148. border-radius: 15px;
  149. margin-bottom: 1rem;
  150. background: #b24592;
  151. background: -webkit-linear-gradient(to right, #b24592, #f15f79);
  152. background: linear-gradient(to right, #b24592, #f15f79);
  153. overflow: hidden;
  154. border: 1px solid var(--border-color);
  155. .username {
  156. color: #fff;
  157. }
  158. .avatar {
  159. border-radius: 6px;
  160. margin-bottom: 5px;
  161. }
  162. &.seen {
  163. opacity: 30%;
  164. }
  165. &-blur {
  166. border-radius: 15px;
  167. overflow: hidden;
  168. background: rgba(0, 0, 0, 0.2);
  169. backdrop-filter: blur(8px);
  170. }
  171. }
  172. }
  173. }
  174. .force-dark-mode {
  175. .story-wrapper {
  176. &.seen {
  177. opacity: 50%;
  178. background: linear-gradient(rgba(255,255,255,0.12),rgba(255,255,255,0.14)) !important;
  179. }
  180. }
  181. }
  182. </style>