@ -1,154 +1,167 @@
< template >
< div class = " container mt-2 mt-md-5 bg-black">
< div class = " story-compose-component container mt-2 mt-md-5 bg-black">
< input type = "file" id = "pf-dz" name = "media" class = "d-none file-input" v -bind :accept ="config.mimes" >
< span class = "fixed-top text-right m-3 cursor-pointer" @click ="navigateTo()" >
< i class = "fa s fa-times fa-lg text-white "> < / i >
< i class = "fa l fa-times-circle fa-2x text-lighter "> < / i >
< / span >
< div v-if ="loaded" class="row" >
< div class = "col-12 col-md-6 offset-md-3 bg-dark rounded-lg ">
< div class = "col-12 col-md-6 offset-md-3 bg-dark rounded-lg px-0 ">
<!-- LANDING -- >
< div v-if ="page == 'landing'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;" >
< div class = "text-center flex-fill pt-3" >
< p class = "text-muted font-weight-light mb-1" >
< i class = "fas fa-history fa-5x" > < / i >
< / p >
< p class = "text-muted font-weight-bold mb-0" > STORIES < / p >
< img class = "mb-2" src = "/img/pixelfed-icon-color.svg" width = "70" height = "70" >
< p class = "lead text-lighter font-weight-light mb-0" > Stories < / p >
< / div >
< div class = "flex-fill py-4" >
< p class = "text-center lead font-weight-light text-lighter mb-4" > Share moments with followers that last 24 hours < / p >
< div class = "card w-100 shadow-none bg-transparent" >
< div class = "list-group bg-transparent" >
<!-- < a class = "list-group-item text-center lead text-decoration-none text-dark" href = "#" > Camera < / a > -- >
< a class = "list-group-item bg-transparent lead text-decoration-none text-light font-weight-bold border-light" href = "#" @click.prevent ="upload()" >
< i class = "fas fa-plus-square mr-2" > < / i >
< div class = "d-flex" >
< button type = "button" class = "btn btn-outline-light btn-lg font-weight-bold btn-block rounded-pill my-1" : disabled = "stories.length >= 20" @click ="upload()" >
Add to Story
< / a >
< a v-if ="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()" >
< i class = "far fa-clone mr-2" > < / i >
My Story
< / a >
< a v-if ="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="viewMyStory()" >
< i class = "fas fa-history mr-2" > < / i >
View My Story
< / a >
<!-- < a v-if ="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()" >
< i class = "fas fa-network-wired mr-1" > < / i >
Audience
< / a > -- >
<!-- < a v-if ="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()" >
< i class = "far fa-chart-bar mr-2" > < / i >
Stats
< / a > -- >
<!-- < a class = "list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href = "#" @click.prevent ="edit()" >
< i class = "far fa-folder mr-2" > < / i >
Archived
< / a > -- >
<!-- < a class = "list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href = "#" @click.prevent ="edit()" >
< i class = "far fa-question-circle mr-2" > < / i >
Help
< / a > -- >
< a class = "list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href = "/" >
< i class = "fas fa-arrow-left mr-2" > < / i >
Go back
< / a >
<!-- < a class = "list-group-item text-center lead text-decoration-none text-dark" href = "#" > Options < / a > -- >
< / button >
<!-- < button : disabled = "stories.length >= 20" type = "button" class = "btn btn-outline-light btn-lg font-weight-bold btn-block rounded-pill my-1 ml-2" @click ="newPoll" >
Create Poll
< / button > -- >
< / div >
< p
v - if = "stories.length >= 20"
class = "font-weight-bold text-muted text-center" >
You have reached the limit for new stories
< / p >
< button
type = "button"
class = "btn btn-outline-light btn-lg font-weight-bold btn-block rounded-pill my-3"
@ click = "viewMyStory"
: disabled = "stories.length == 0" >
< span > My Story < / span >
< sup v-if ="stories.length" class="ml-2 px-2 text-light bg-danger rounded-pill" style="font-size: 12px;padding-top:2px;padding-bottom:3px;" > {{ stories.length }} < / sup >
< / button >
< / div >
< / div >
< div class = "text-center flex-fill" >
<!-- < p class = "text-lighter small text-uppercase" >
< a href = "/" class = "text-muted font-weight-bold" > Home < / a >
< p class = "text-uppercase mb-0" >
< a href = "/" class = "text-lighter font-weight-bold" > Home < / a >
< span class = "px-2 text-lighter" > | < / span >
< a href = "/i/my/story" class = "text-muted font-weight-bold" > View My Story < / a >
< span class = "px-2 text-lighter" > | < / span >
< a href = "/site/help" class = "text-muted font-weight-bold" > Help < / a >
< / p > -- >
< a href = "/site/help" class = "text-lighter font-weight-bold" > Help < / a >
< / p >
< p class = "small text-muted mb-0" > v 1.0 .0 < / p >
< / div >
< / div >
<!-- CROP -- >
< div v-if ="page == 'crop'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;" >
< div class = "text-center py-3 d-flex justify-content-between align-items-center" >
< div >
< button class = "btn btn-outline-lighter btn-sm py-1 px-md-3" @click ="deleteCurrentStory()" > < i class = "pr-2 fas fa-chevron-left fa-sm" > < / i > Delete < / button >
< / div >
< div class = "" >
< p class = "text-muted font-weight-light mb-1" >
< i class = "fas fa-history fa-5x" > < / i >
< / p >
< p class = "text-muted font-weight-bold mb-0" > STORIES < / p >
< / div >
< div >
< button class = "btn btn-primary btn-sm py-1 px-md-3" @click ="performCrop()" > Crop < i class = "pl-2 fas fa-chevron-right fa-sm" > < / i > < / button >
< / div >
< / div >
< div class = "flex-fill" >
< div class = "card w-100 mt-3" >
< div class = "card-body p-0" >
< vue -cropper
ref = "croppa"
: relativeZoom = "cropper.zoom"
: aspectRatio = "cropper.aspectRatio"
: viewMode = "cropper.viewMode"
: zoomable = "cropper.zoomable"
: rotatable = "true"
: src = "mediaUrl"
>
< / v u e - c r o p p e r >
< div v -else -if = " page = = ' crop ' " class = "d-flex justify-content-center flex-fill" style = "position: relative;height: 90vh;" >
< vue -cropper
class = "w-100 h-100 p-0"
ref = "croppa"
: aspectRatio = "cropper.aspectRatio"
: viewMode = "3"
: dragMode = "'move'"
: autoCropArea = "1"
: guides = "false"
: highlight = "false"
: cropBoxMovable = "false"
: cropBoxResizable = "false"
: toggleDragModeOnDblclick = "false"
: src = "mediaUrl"
>
< / v u e - c r o p p e r >
< div class = "crop-container" >
< div class = "d-flex justify-content-between align-items-center" >
< button
type = "button"
class = "btn btn-outline-muted rounded-pill font-weight-bold px-4"
@ click = "deleteCurrentStory()" >
Cancel
< / button >
< div class = "text-center" >
< h4 class = "font-weight-light text-light mb-n1" > Crop < / h4 >
< span class = "small text-light" > Pan around and pinch to zoom < / span >
< / div >
< button
type = "button"
class = "btn btn-outline-light rounded-pill font-weight-bold px-4"
@ click = "performCrop()" >
Next
< / button >
< / div >
< / div >
< / div >
<!-- ERROR -- >
< div v-if ="page == 'error'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;" >
< p class = "h3 mb-0 text-light" > Oops ! < / p >
< p class = "text-muted lead" > An error occurred , please try again later . < / p >
< p class = "text-muted mb-0" >
< a class = "btn btn-outline-secondary py-0 px-5 font-weight-bold" href = "/" > Go back < / a >
< / p >
< div v -else -if = " page = = ' error ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style = "height: 90vh;" >
< div class = "text-center flex-fill pt-3" >
< img class = "mb-2" src = "/img/pixelfed-icon-color.svg" width = "70" height = "70" >
< p class = "lead text-lighter font-weight-light mb-0" > Stories < / p >
< / div >
< div class = "flex-fill text-center" >
< p class = "h3 mb-0 text-light" > Oops ! < / p >
< p class = "text-muted lead" > An error occurred , please try again later . < / p >
< p class = "text-muted mb-0" >
< a class = "btn btn-outline-muted py-0 px-5 rounded-pill font-weight-bold" href = "/" > Go back < / a >
< / p >
< / div >
< / div >
<!-- UPLOADING -- >
< div v-if ="page == 'uploading'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;" >
< p v-if ="uploadProgress != 100" class="display-4 mb-0 text-muted" > Uploading {{ uploadProgress }} % < / p >
< p v -else class = "display-4 mb-0 text-muted" > Processing ... < / p >
< div v -else -if = " page = = ' uploading ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style = "height: 90vh;" >
< div class = "spinner-border text-lighter" role = "status" >
< span class = "sr-only" > Loading ... < / span >
< / div >
< / div >
<!-- CROPPING -- >
< div v-if ="page == 'cropping'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;" >
< p class = "display-4 mb-0 text-muted" > Cropping ... < / p >
< div v -else -if = " page = = ' cropping ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style = "height: 90vh;" >
< div class = "spinner-border text-lighter" role = "status" >
< span class = "sr-only" > Loading ... < / span >
< / div >
< / div >
<!-- PREVIEW -- >
< div v-if ="page == 'preview'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;" >
< div >
< div class = "form-group" >
< div v -else -if = " page = = ' preview ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style = "height: 90vh;" >
< div class = "text-center flex-fill pt-3" >
< img class = "mb-2" src = "/img/pixelfed-icon-color.svg" width = "70" height = "70" >
< p class = "lead text-lighter font-weight-light mb-0" > Stories < / p >
< / div >
< div class = "flex-fill" >
< div class = "form-group pb-3" >
< label for = "durationSlider" class = "text-light lead font-weight-bold" > Options < / label >
< div class = "custom-control custom-checkbox mb-2" >
< input type = "checkbox" class = "custom-control-input" id = "optionReplies" v-model ="canReply" >
< label class = "custom-control-label text-light font-weight-lighter" for = "optionReplies" > Allow replies < / label >
< / div >
< div class = "custom-control custom-checkbox mb-2" >
< input type = "checkbox" class = "custom-control-input" id = "formReactions" v-model ="canReact" >
< label class = "custom-control-label text-light font-weight-lighter" for = "formReactions" > Allow reactions < / label >
< / div >
< / div >
< div v-if ="!canPostPoll" class="form-group" >
< video ref = "previewVideo" v-if ="mediaType == 'video'" class="mb-4 w-100" style="max-height:200px;object-fit:contain;" >
< source :src ="mediaUrl" type = "video/mp4" >
< / video >
< label for = "durationSlider" class = "text-light lead font-weight-bold" > Story Duration < / label >
< input type = "range" class = "custom-range" min = "3" max = "10" id = "durationSlider" v-model ="duration" >
< input type = "range" class = "custom-range" min = "3" :max ="max_duration" step = "1 " id = "durationSlider" v-model ="duration" >
< p class = "help-text text-center" >
< span class = "text-light" > { { duration } } seconds < / span >
< / p >
< / div >
< hr class = "my-3" >
< a class = "btn btn-primary btn-block px-5 font-weight-bold my-3" href = "#" @click.prevent ="shareStoryToFollowers()" >
Share Story with followers
< / a >
< a class = "btn btn-outline-muted btn-block px-5 font-weight-bold" href = "/" @click.prevent ="deleteCurrentStory()" >
Cancel
< / a >
< / div >
<!-- < a class = "btn btn-outline-secondary btn-block px-5 font-weight-bold" href = "#" >
Share Story with everyone
< / a > -- >
< div class = "flex-fill w-100 px-md-5" >
< div class = "d-flex" >
< a class = "btn btn-outline-muted btn-block font-weight-bold my-3 mr-3 rounded-pill" href = "/" @click.prevent ="deleteCurrentStory()" >
Cancel
< / a >
< a class = "btn btn-primary btn-block font-weight-bold my-3 rounded-pill" href = "#" @click.prevent ="shareStoryToFollowers()" >
Post { { canPostPoll ? 'Poll' : 'Story' } }
< / a >
< / div >
< / div >
< / div >
<!-- EDIT -- >
< div v-if ="page == 'edit'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;" >
< div v -else -if = " page = = ' edit ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style = "height: 90vh;" >
< div class = "text-center flex-fill mt-5" >
< p class = "text-muted font-weight-light mb-1" >
< i class = "fas fa-history fa-5x" > < / i >
< i class = "fa l fa-history fa-5x"> < / i >
< / p >
< p class = "text-muted font-weight-bold mb-0" > STORIES < / p >
< / div >
@ -162,14 +175,14 @@
< img :src ="story.src" class = "rounded-circle border" width = "40px" height = "40px" style = "object-fit: cover;" >
< / div >
< div class = "media-body text-left" >
< p class = "mb-0 text-muted font-weight-bold" > < span > { { story. created _ago } } ago < / span > < / p >
< p class = "mb-0 text-muted font-weight-bold" > < span > { { timeago( story . created _at ) } } ago < / span > < / p >
< / div >
< div class = "flex-grow-1 text-right" >
< button v-if ="story.viewers.length" @click="toggleShowViewers(index)" class="btn btn-link btn-sm mr-1" >
< i class = "fa s fa-eye fa-lg text-muted"> < / i >
< i class = "fa l fa-eye fa-lg text-muted"> < / i >
< / button >
< button @ click = "deleteStory(story, index)" class = "btn btn-link btn-sm" >
< i class = "fa s fa-trash-alt fa-lg text-muted"> < / i >
< i class = "fa l fa-trash-alt fa-lg text-muted"> < / i >
< / button >
< / div >
< / div >
@ -188,8 +201,58 @@
< a class = "btn btn-outline-secondary btn-block px-5 font-weight-bold" href = "/i/stories/new" @click.prevent ="goBack()" > Go back < / a >
< / div >
< / div >
< div v -else -if = " page = = ' createPoll ' " class = "card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style = "height: 90vh;" >
< div class = "text-center pt-3" >
< img class = "mb-2" src = "/img/pixelfed-icon-color.svg" width = "70" height = "70" >
< p class = "lead text-lighter font-weight-light mb-0" > Stories < / p >
< / div >
< div class = "flex-fill mt-3" >
< div class = "align-items-center" >
< div class = "form-group mb-5" >
< label class = "font-weight-bold text-lighter" > Poll Question < / label >
< input class = "form-control form-control-lg rounded-pill bg-muted shadow text-white border-0" placeholder = "Ask a poll question here..." v -model = " pollQuestion " / >
< / div >
< label class = "font-weight-bold text-lighter" > Poll Answers < / label >
< div v-for ="(option, index) in pollOptions" class="form-group mb-4" >
< input class = "form-control form-control-lg rounded-pill bg-muted shadow text-white border-0" placeholder = "Add a poll answer here..." v -model = " pollOptions [ index ] " / >
< / div >
< div v-if ="pollOptions.length < 4" class="mb-3" >
< button
class = "btn btn-block font-weight-bold rounded-pill shadow"
: class = "[ (pollQuestion && pollQuestion.length) > 6 && (pollOptions.length == 0 || pollOptions.length && pollOptions[pollOptions.length - 1].length > 3) ? 'btn-muted' : 'btn-outline-muted' ]"
: disabled = "!pollQuestion || pollQuestion.length < 6"
@ click = "addOptionInput" >
Add poll option
< / button >
< / div >
<!-- < div v-for ="(option, index) in pollOptions" class="form-group mb-4 d-flex align-items-center" style="max-width:400px;position: relative;" >
< span class = "font-weight-bold mr-2" style = "position: absolute;left: 10px;" > { { index + 1 } } . < / span >
< input v-if ="pollOptions[index].length < 50" type="text" class="form-control rounded-pill" placeholder="Add a poll option, press enter to save" v-model="pollOptions[index]" style="padding-left: 30px;padding-right: 90px;" >
< textarea v -else class = "form-control" v-model ="pollOptions[index]" placeholder="Add a poll option, press enter to save" rows="3" style="padding-left: 30px;padding-right:90px;" > < / textarea >
< button class = "btn btn-danger btn-sm rounded-pill font-weight-bold" style = "position: absolute;right: 5px;" @click ="deletePollOption(index)" >
< i class = "fas fa-trash" > < / i > Delete
< / button >
< / div > -- >
< / div >
< / div >
< div class = "flex-fill text-center" >
< a v-if ="canPostPoll" class="btn btn-outline-light btn-block px-5 font-weight-bold rounded-pill" href="/i/stories/new" @click.prevent="pollPreview" > Next < / a >
< a class = "btn btn-outline-secondary btn-block px-5 font-weight-bold rounded-pill" href = "/i/stories/new" @click.prevent ="goBack()" > Go back < / a >
< / div >
< / div >
< / div >
< / div >
< div v -else class = "row" >
< div class = "col-12 col-md-6 offset-md-3 bg-dark rounded-lg px-0" style = "height: 90vh;" >
< div class = "w-100 h-100 d-flex justify-content-center align-items-center" >
< div class = "spinner-border text-lighter" role = "status" >
< span class = "sr-only" > Loading ... < / span >
< / div >
< / div >
< / div >
< / div >
< b -modal
id = "lightbox"
ref = "lightboxModal"
@ -207,19 +270,11 @@
< / div >
< / template >
< style type = "text/css" >
. bg - black {
background - color : # 262626 ;
}
# lightbox . modal - content {
background : transparent ;
}
< / style >
< script type = "text/javascript" >
import VueTimeago from 'vue-timeago' ;
import VueCropper from 'vue-cropperjs' ;
import 'cropperjs/dist/cropper.css' ;
export default {
components : {
VueCropper ,
@ -234,7 +289,7 @@
mimes : [
'image/jpeg' ,
'image/png' ,
/ / ' v i d e o / m p 4 '
'video/mp4 '
] ,
page : 'landing' ,
pages : [
@ -243,36 +298,79 @@
'edit' ,
'confirm' ,
'error' ,
'uploading'
'uploading' ,
'createPoll'
] ,
uploading : false ,
uploadProgress : 0 ,
cropper : {
aspectRatio : 9 / 16 ,
viewMode : 2 ,
viewMode : 3 ,
zoomable : true ,
zoom : null
} ,
mediaUrl : null ,
mediaId : null ,
mediaType : null ,
stories : [ ] ,
lightboxMedia : false ,
duration : 3
duration : 10 ,
canReply : true ,
canReact : true ,
poll : {
question : null ,
options : [ ]
} ,
pollQuestion : null ,
pollOptions : [ ] ,
canPostPoll : false ,
max _duration : 15
} ;
} ,
watch : {
duration : function ( val ) {
if ( this . mediaType == 'video' ) {
this . $refs . previewVideo . currentTime = val ;
this . $refs . previewVideo . play ( ) ;
}
} ,
pollQuestion : function ( val ) {
if ( val . length < 6 ) {
this . canPostPoll = false ;
}
} ,
pollOptions : function ( val ) {
let len = this . pollOptions . filter ( o => {
return o . length >= 2 ;
} ) ;
if ( len . length >= 2 ) {
this . canPostPoll = true ;
} else {
this . canPostPoll = false ;
}
}
} ,
mounted ( ) {
$ ( 'body' ) . addClass ( 'bg-black' ) ;
this . mediaWatcher ( ) ;
axios . get ( '/api/stories/v0/fetch/' + this . profileId )
. then ( res => {
this . stories = res . data . map ( s => {
s . showViewers = false ;
s . viewers = [ ] ;
return s ;
setTimeout ( ( ) => {
axios . get ( '/api/web/stories/v1/profile/' + this . profileId )
. then ( res => {
if ( res . data . length ) {
this . stories = res . data [ 0 ] . nodes . map ( s => {
s . showViewers = false ;
s . viewers = [ ] ;
return s ;
} ) ;
}
this . loaded = true ;
} ) ;
this . loaded = true ;
} ) ;
} , 400 ) ;
} ,
methods : {
@ -321,23 +419,28 @@
} ;
io . value = null ;
axios . post ( '/api/ stories/v0 /add', form , xhrConfig )
axios . post ( '/api/ web/stories/v1 /add', form , xhrConfig )
. then ( function ( e ) {
self . uploadProgress = 100 ;
self . uploading = false ;
self . mediaUrl = e . data . media _url ;
self . mediaId = e . data . media _id ;
self . mediaType = e . data . media _type ;
self . page = e . data . media _type === 'video' ? 'preview' : 'crop' ;
if ( e . data . hasOwnProperty ( 'media_duration' ) ) {
self . max _duration = e . data . media _duration ;
}
/ / w i n d o w . l o c a t i o n . h r e f = ' / i / m y / s t o r y ' ;
} ) . catch ( function ( e ) {
self . uploading = false ;
io . value = null ;
let msg = e . response . data . message ? e . response . data . message : 'Something went wrong.'
let msg = e . response . data . message ? e . response . data . message : e . response . data . error ? e . response . data . error : 'Something went wrong.'
swal ( 'Oops!' , msg , 'warning' ) ;
self . page = 'error' ;
} ) ;
self . uploadProgress = 0 ;
} ) ;
document . querySelector ( '#pf-dz' ) . value = '' ;
} ,
expiresTimestamp ( ts ) {
@ -361,7 +464,7 @@
return ;
}
axios . delete ( '/api/ stories/v0 /delete/' + story . id )
axios . delete ( '/api/ web/stories/v1 /delete/' + story . id )
. then ( res => {
this . stories . splice ( index , 1 ) ;
if ( this . stories . length == 0 ) {
@ -381,7 +484,7 @@
performCrop ( ) {
this . page = 'cropping' ;
let data = this . $refs . croppa . getData ( ) ;
axios . post ( '/api/ stories/v0 /crop', {
axios . post ( '/api/ web/stories/v1 /crop', {
media _id : this . mediaId ,
width : data . width ,
height : data . height ,
@ -401,12 +504,25 @@
} ,
shareStoryToFollowers ( ) {
axios . post ( '/api/stories/v0/publish' , {
media _id : this . mediaId ,
duration : this . duration
} ) . then ( res => {
window . location . href = '/i/my/story?id=' + this . mediaId ;
} )
if ( this . canPostPoll ) {
axios . post ( '/api/web/stories/v1/publish/poll' , {
question : this . pollQuestion ,
options : this . pollOptions ,
can _reply : this . canReply ,
can _react : this . canReact
} ) . then ( res => {
window . location . href = '/i/my/story?id=' + this . mediaId ;
} )
} else {
axios . post ( '/api/web/stories/v1/publish' , {
media _id : this . mediaId ,
duration : this . duration ,
can _reply : this . canReply ,
can _react : this . canReact
} ) . then ( res => {
window . location . href = '/i/my/story?id=' + this . mediaId ;
} )
}
} ,
viewMyStory ( ) {
@ -415,7 +531,62 @@
toggleShowViewers ( index ) {
this . stories [ index ] . showViewers = this . stories [ index ] . showViewers ? false : true ;
} ,
timeago ( ts ) {
return App . util . format . timeAgo ( ts ) ;
} ,
newPoll ( ) {
this . page = 'createPoll' ;
} ,
addOptionInput ( ) {
let c = this . pollOptions . filter ( o => {
return o . length < 3 ;
} ) ;
if ( c . length ) {
return ;
}
this . pollOptions . push ( [ ] ) ;
} ,
pollPreview ( ) {
let opts = this . pollOptions ;
let dd = [ ... new Set ( this . pollOptions ) ] ;
if ( dd . length != opts . length ) {
swal ( 'Oops!' , 'You cannot use duplicate poll answers, please remove any duplicates and try again.' , 'error' ) ;
return ;
}
this . page = 'preview' ;
}
}
}
< / script >
< style lang = "scss" >
. bg - black {
background - color : # 262626 ;
}
< / style >
< style lang = "scss" scoped >
. story - compose - component {
# lightbox . modal - content {
background : transparent ;
}
: : placeholder {
color : # ccc ;
}
. crop - container {
z - index : 9 ;
position : absolute ;
top : 0 ;
width : 100 % ;
min - height : 100 px ;
padding : 15 px 30 px ;
background : linear - gradient ( 180 deg , rgba ( 38 , 38 , 38 , 0.8 ) 0 % , rgba ( 38 , 38 , 38 , 0 ) 100 % ) ;
}
}
< / style >