diff options
Diffstat (limited to 'src/components')
21 files changed, 222 insertions, 103 deletions
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 20d10cce..d6a51ffd 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -34,6 +34,13 @@ display: flex; flex-wrap: wrap; margin-right: -0.7em; + + .attachment.media-upload-container { + flex: 0 0 auto; + max-height: 300px; + max-width: 100%; + } + .attachment { flex: 1 0 30%; margin: 0.5em 0.7em 0.6em 0.0em; @@ -82,9 +89,7 @@ img.media-upload { margin-bottom: -2px; max-height: 300px; - width: 100%; - height: 100%; - flex: 1; + max-width: 100%; } .oembed { @@ -126,6 +131,7 @@ width: 100%; height: 100%; /* If this isn't here, chrome will stretch the images */ max-height: 500px; + image-orientation: from-image; } } } diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js new file mode 100644 index 00000000..ef326d4a --- /dev/null +++ b/src/components/chat/chat.js @@ -0,0 +1,21 @@ +const chat = { + data () { + return { + currentMessage: '', + channel: null + } + }, + computed: { + messages () { + return this.$store.state.chat.messages + } + }, + methods: { + submit (message) { + this.$store.state.chat.channel.push('new_msg', {text: message}, 10000) + this.currentMessage = '' + } + } +} + +export default chat diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue new file mode 100644 index 00000000..6c1e2c38 --- /dev/null +++ b/src/components/chat/chat.vue @@ -0,0 +1,59 @@ +<template> + <div class="chat-panel panel panel-default"> + <div class="panel-heading timeline-heading base02-background base04"> + <div class="title"> + {{$t('chat.title')}} + </div> + </div> + <div class="panel-body base01-background"> + <div class="chat-window"> + <div class="chat-message" v-for="message in messages" :key="message.id"> + <span class="chat-avatar"> + <img :src="message.author.avatar" /> + {{message.author.username}}: + </span> + <span class="chat-text"> + {{message.text}} + </span> + </div> + </div> + <div class="chat-input"> + <form @submit.prevent="submit(currentMessage)"> + <input v-model="currentMessage" type="text" > + </form> + </div> + </div> + </div> +</template> + +<script src="./chat.js"></script> + + +<style lang="scss"> + .chat-window { + max-height: 80vh; + overflow-y: auto; + overflow-x: hidden; + } + .chat-message { + padding: 0.2em 0.5em + } + .chat-avatar { + img { + height: 32px; + width: 32px; + border-radius: 5px; + margin-right: 0.5em; + } + } + .chat-input { + display: flex; + form { + flex: auto; + input { + margin: 0.5em; + width: fill-available; + } + } + } +</style> diff --git a/src/components/delete_button/delete_button.vue b/src/components/delete_button/delete_button.vue index 304f8a63..845ac777 100644 --- a/src/components/delete_button/delete_button.vue +++ b/src/components/delete_button/delete_button.vue @@ -1,7 +1,7 @@ <template> <div v-if="canDelete"> <a href="#" v-on:click.prevent="deleteStatus()"> - <i class='fa icon-cancel delete-status'></i> + <i class='base09 icon-cancel delete-status'></i> </a> </div> </template> diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue index 0abece31..dcf28e35 100644 --- a/src/components/favorite_button/favorite_button.vue +++ b/src/components/favorite_button/favorite_button.vue @@ -1,6 +1,6 @@ <template> <div> - <i :class='classes' class='favorite-button fa' @click.prevent='favorite()'/> + <i :class='classes' class='favorite-button base09' @click.prevent='favorite()'/> <span v-if='status.fave_num > 0'>{{status.fave_num}}</span> </div> </template> @@ -15,7 +15,7 @@ color: orange; } } - .icon-star { + .favorite-button.icon-star { color: orange; } diff --git a/src/components/media_upload/media_upload.vue b/src/components/media_upload/media_upload.vue index b839067b..9e6ad608 100644 --- a/src/components/media_upload/media_upload.vue +++ b/src/components/media_upload/media_upload.vue @@ -1,8 +1,8 @@ <template> <div class="media-upload" @drop.prevent @dragover.prevent="fileDrag" @drop="fileDrop"> <label class="btn btn-default"> - <i class="fa icon-spin4 animate-spin" v-if="uploading"></i> - <i class="fa icon-upload" v-if="!uploading"></i> + <i class="base09 icon-spin4 animate-spin" v-if="uploading"></i> + <i class="base09 icon-upload" v-if="!uploading"></i> <input type=file style="position: fixed; top: -100em"></input> </label> </div> diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index baeaaede..ea5d7ea4 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -2,6 +2,9 @@ const NavPanel = { computed: { currentUser () { return this.$store.state.users.currentUser + }, + chat () { + return this.$store.state.chat.channel } } } diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue index aea841e9..ccc772a8 100644 --- a/src/components/nav_panel/nav_panel.vue +++ b/src/components/nav_panel/nav_panel.vue @@ -7,6 +7,11 @@ {{ $t("nav.timeline") }} </router-link> </li> + <li v-if='chat && currentUser'> + <router-link class="base00-background" to='/chat'> + {{ $t("nav.chat") }} + </router-link> + </li> <li v-if='currentUser'> <router-link class="base00-background" :to="{ name: 'mentions', params: { username: currentUser.screen_name } }"> {{ $t("nav.mentions") }} diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss index db7b0843..241f10b4 100644 --- a/src/components/notifications/notifications.scss +++ b/src/components/notifications/notifications.scss @@ -59,6 +59,10 @@ color: $blue; } + .icon-star.lit { + color: orange; + } + .status-content { margin: 0; max-height: 300px; diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue index 64624873..b341fcef 100644 --- a/src/components/notifications/notifications.vue +++ b/src/components/notifications/notifications.vue @@ -4,7 +4,7 @@ <div class="panel-heading base02-background base04"> <span class="unseen-count" v-if="unseenCount">{{unseenCount}}</span> {{$t('notifications.notifications')}} - <button @click.prevent="markAsSeen" class="base04 base02-background read-button">{{$t('notifications.read')}}</button> + <button v-if="unseenCount" @click.prevent="markAsSeen" class="base04 base02-background read-button">{{$t('notifications.read')}}</button> </div> <div class="panel-body base03-border"> <div v-for="notification in visibleNotifications" :key="notification" class="notification" :class='{"unseen": !notification.seen}'> @@ -17,7 +17,7 @@ <div v-if="notification.type === 'favorite'"> <h1> <span :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span> - <i class="fa icon-star"></i> + <i class="fa icon-star lit"></i> <small><router-link :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small> </h1> <div class="notification-gradient" :style="hiderStyle"></div> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 2eb091f4..8c0cd5ee 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -157,6 +157,14 @@ const PostStatusForm = { type (fileInfo) { return fileTypeService.fileType(fileInfo.mimetype) }, + paste (e) { + if (e.clipboardData.files.length > 0) { + // Strangely, files property gets emptied after event propagation + // Trying to wrap it in array doesn't work. Plus I doubt it's possible + // to hold more than one file in clipboard. + this.dropFiles = [e.clipboardData.files[0]] + } + }, fileDrop (e) { if (e.dataTransfer.files.length > 0) { e.preventDefault() // allow dropping text like before diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 8a2ec24d..8e436428 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -2,7 +2,7 @@ <div class="post-status-form"> <form @submit.prevent="postStatus(newStatus)"> <div class="form-group base03-border" > - <textarea @click="setCaret" @keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control" @keydown.meta.enter="postStatus(newStatus)" @keyup.ctrl.enter="postStatus(newStatus)" @drop="fileDrop" @dragover.prevent="fileDrag" @input="resize"></textarea> + <textarea @click="setCaret" @keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control" @keydown.meta.enter="postStatus(newStatus)" @keyup.ctrl.enter="postStatus(newStatus)" @drop="fileDrop" @dragover.prevent="fileDrag" @input="resize" @paste="paste"></textarea> </div> <div style="position:relative;" v-if="candidates"> <div class="autocomplete-panel base05-background"> @@ -26,7 +26,7 @@ <i class="icon-cancel" @click="clearError"></i> </div> <div class="attachments"> - <div class="attachment base03-border" v-for="file in newStatus.files"> + <div class="media-upload-container attachment base03-border" v-for="file in newStatus.files"> <i class="fa icon-cancel" @click="removeMediaFile(file)"></i> <img class="thumbnail media-upload" :src="file.image" v-if="type(file) === 'image'"></img> <video v-if="type(file) === 'video'" :src="file.image" controls></video> @@ -41,6 +41,7 @@ <script src="./post_status_form.js"></script> <style lang="scss"> + .tribute-container { ul { padding: 0px; diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue index d923c5c4..edbfef32 100644 --- a/src/components/retweet_button/retweet_button.vue +++ b/src/components/retweet_button/retweet_button.vue @@ -1,6 +1,6 @@ <template> <div> - <i :class='classes' class='icon-retweet fa' v-on:click.prevent='retweet()'></i> + <i :class='classes' class='icon-retweet base09' v-on:click.prevent='retweet()'></i> <span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span> </div> </template> @@ -16,7 +16,7 @@ color: $green; } } - .retweeted { + .icon-retweet.retweeted { color: $green; } </style> diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 5e3df8ba..d6c8cdb3 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -5,7 +5,7 @@ <div class='status-actions'> <div> <a href="#" v-on:click.prevent="toggleReplying"> - <i class="fa icon-reply" :class="{'icon-reply-active': replying}"></i> + <i class="base09 icon-reply" :class="{'icon-reply-active': replying}"></i> </a> </div> <retweet-button :status=status></retweet-button> @@ -19,7 +19,7 @@ <div class="media status container muted"> <small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small> <small class="muteWords">{{muteWordHits.join(', ')}}</small> - <a href="#" class="unmute" @click.prevent="toggleMute"><i class="fa icon-eye-off"></i></a> + <a href="#" class="unmute" @click.prevent="toggleMute"><i class="base09 icon-eye-off"></i></a> </div> </template> <template v-if="!muted"> @@ -75,10 +75,10 @@ </h4> </div> <div class="heading-icons"> - <a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="fa icon-eye-off"></i></a> - <a :href="status.external_url" target="_blank" v-if="!status.is_local" class="source_url"><i class="fa icon-binoculars"></i></a> + <a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="base09 icon-eye-off"></i></a> + <a :href="status.external_url" target="_blank" v-if="!status.is_local" class="source_url"><i class="base09 icon-binoculars"></i></a> <template v-if="expandable"> - <a href="#" @click.prevent="toggleExpanded" class="expand"><i class="fa icon-plus-squared"></i></a> + <a href="#" @click.prevent="toggleExpanded" class="expand"><i class="base09 icon-plus-squared"></i></a> </template> </div> </div> @@ -94,7 +94,7 @@ </div> </div> <div class="status-preview status-preview-loading base00-background base03-border" v-else-if="showPreview"> - <i class="fa icon-spin4 animate-spin"></i> + <i class="base09 icon-spin4 animate-spin"></i> </div> <div @click.prevent="linkClicked" class="status-content" v-html="status.statusnet_html"></div> @@ -109,7 +109,7 @@ <div class='status-actions'> <div> <a href="#" v-on:click.prevent="toggleReplying"> - <i class="fa icon-reply" :class="{'icon-reply-active': replying}"></i> + <i class="base09 icon-reply" :class="{'icon-reply-active': replying}"></i> </a> </div> <retweet-button :status=status></retweet-button> @@ -324,7 +324,7 @@ color: $blue; } - .icon-reply-active { + .icon-reply.icon-reply-active { color: $blue; } diff --git a/src/components/style_switcher/style_switcher.js b/src/components/style_switcher/style_switcher.js index b1359d13..a762f914 100644 --- a/src/components/style_switcher/style_switcher.js +++ b/src/components/style_switcher/style_switcher.js @@ -1,3 +1,5 @@ +import { rgbstr2hex } from '../../services/color_convert/color_convert.js' + export default { data () { return { @@ -19,13 +21,6 @@ export default { }) }, mounted () { - const rgbstr2hex = (rgb) => { - if (rgb[0] === '#') { - return rgb - } - rgb = rgb.match(/\d+/g) - return `#${((Number(rgb[0]) << 16) + (Number(rgb[1]) << 8) + Number(rgb[2])).toString(16)}` - } this.bgColorLocal = rgbstr2hex(this.$store.state.config.colors['base00']) this.fgColorLocal = rgbstr2hex(this.$store.state.config.colors['base02']) this.textColorLocal = rgbstr2hex(this.$store.state.config.colors['base05']) diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index be0aefc1..660a8752 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -29,6 +29,13 @@ const Timeline = { }, newStatusCount () { return this.timeline.newStatusCount + }, + newStatusCountStr () { + if (this.timeline.flushMarker !== 0) { + return '' + } else { + return ` (${this.newStatusCount})` + } } }, components: { @@ -64,8 +71,14 @@ const Timeline = { }, methods: { showNewStatuses () { - this.$store.commit('showNewStatuses', { timeline: this.timelineName }) - this.paused = false + if (this.timeline.flushMarker !== 0) { + this.$store.commit('clearTimeline', { timeline: this.timelineName }) + this.$store.commit('queueFlush', { timeline: this.timelineName, id: 0 }) + this.fetchOlderStatuses() + } else { + this.$store.commit('showNewStatuses', { timeline: this.timelineName }) + this.paused = false + } }, fetchOlderStatuses () { const store = this.$store diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 0e2ed92c..9d2e1ea1 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -5,7 +5,7 @@ {{title}} </div> <button @click.prevent="showNewStatuses" class="base05 base02-background loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError"> - {{$t('timeline.show_new')}} ({{timeline.newStatusCount}}) + {{$t('timeline.show_new')}}{{newStatusCountStr}} </button> <div @click.prevent class="base06 error loadmore-text" v-if="timelineError"> {{$t('timeline.error_fetching')}} diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index ba315faa..dd14d1b4 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -59,13 +59,16 @@ } .usercard { - width: -webkit-fill-available; - width: -moz-webkit-fill-available; - stretch: fill; + width: fill-available; margin: 0.2em 0 0.7em 0; - border-radius: 5px; + border-radius: 10px; border-style: solid; border-color: inherit; border-width: 1px; + overflow: hidden; + + p { + margin-bottom: 0; + } } </style> diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js new file mode 100644 index 00000000..6e67a321 --- /dev/null +++ b/src/components/user_card_content/user_card_content.js @@ -0,0 +1,64 @@ +import { hex2rgb } from '../../services/color_convert/color_convert.js' + +export default { + props: [ 'user', 'switcher' ], + computed: { + headingStyle () { + const color = this.$store.state.config.colors['base00'] + if (color) { + const rgb = hex2rgb(color) + console.log(rgb) + return { + backgroundColor: `rgb(${Math.floor(rgb[0] * 0.53)}, ${Math.floor(rgb[1] * 0.56)}, ${Math.floor(rgb[2] * 0.59)})`, + backgroundImage: `url(${this.user.cover_photo})` + } + } + }, + bodyStyle () { + return { + background: `linear-gradient(to bottom, rgba(0, 0, 0, 0), ${this.$store.state.config.colors['base00']} 80%)` + } + }, + isOtherUser () { + return this.user.id !== this.$store.state.users.currentUser.id + }, + loggedIn () { + return this.$store.state.users.currentUser + }, + dailyAvg () { + const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000)) + return Math.round(this.user.statuses_count / days) + } + }, + methods: { + followUser () { + const store = this.$store + store.state.api.backendInteractor.followUser(this.user.id) + .then((followedUser) => store.commit('addNewUsers', [followedUser])) + }, + unfollowUser () { + const store = this.$store + store.state.api.backendInteractor.unfollowUser(this.user.id) + .then((unfollowedUser) => store.commit('addNewUsers', [unfollowedUser])) + }, + blockUser () { + const store = this.$store + store.state.api.backendInteractor.blockUser(this.user.id) + .then((blockedUser) => store.commit('addNewUsers', [blockedUser])) + }, + unblockUser () { + const store = this.$store + store.state.api.backendInteractor.unblockUser(this.user.id) + .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser])) + }, + toggleMute () { + const store = this.$store + store.commit('setMuted', {user: this.user, muted: !this.user.muted}) + store.state.api.backendInteractor.setUserMute(this.user) + }, + setProfileView (v) { + const store = this.$store + store.commit('setProfileView', { v }) + } + } +} diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index 5635a177..4c40c55f 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -84,69 +84,7 @@ </div> </template> -<script> - export default { - props: [ 'user', 'switcher' ], - computed: { - headingStyle () { - let color = this.$store.state.config.colors['base00'] - if (color) { - let rgb = this.$store.state.config.colors['base00'].match(/\d+/g) - return { - backgroundColor: `rgb(${Math.floor(rgb[0] * 0.53)}, ${Math.floor(rgb[1] * 0.56)}, ${Math.floor(rgb[2] * 0.59)})`, - backgroundImage: `url(${this.user.cover_photo})` - } - } - }, - bodyStyle () { - return { - background: `linear-gradient(to bottom, rgba(0, 0, 0, 0), ${this.$store.state.config.colors['base00']} 80%)` - } - }, - isOtherUser () { - return this.user.id !== this.$store.state.users.currentUser.id - }, - loggedIn () { - return this.$store.state.users.currentUser - }, - dailyAvg () { - const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000)) - return Math.round(this.user.statuses_count / days) - } - }, - methods: { - followUser () { - const store = this.$store - store.state.api.backendInteractor.followUser(this.user.id) - .then((followedUser) => store.commit('addNewUsers', [followedUser])) - }, - unfollowUser () { - const store = this.$store - store.state.api.backendInteractor.unfollowUser(this.user.id) - .then((unfollowedUser) => store.commit('addNewUsers', [unfollowedUser])) - }, - blockUser () { - const store = this.$store - store.state.api.backendInteractor.blockUser(this.user.id) - .then((blockedUser) => store.commit('addNewUsers', [blockedUser])) - }, - unblockUser () { - const store = this.$store - store.state.api.backendInteractor.unblockUser(this.user.id) - .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser])) - }, - toggleMute () { - const store = this.$store - store.commit('setMuted', {user: this.user, muted: !this.user.muted}) - store.state.api.backendInteractor.setUserMute(this.user) - }, - setProfileView (v) { - const store = this.$store - store.commit('setProfileView', { v }) - } - } - } -</script> +<script src="./user_card_content.js"></script> <style lang="scss"> @import '../../_variables.scss'; @@ -164,7 +102,6 @@ .profile-panel-body { top: -0em; padding-top: 4em; - word-wrap: break-word; } diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 74b0ff2a..515fd253 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -22,7 +22,7 @@ <div> <input type="file" @change="uploadFile(0, $event)" ></input> </div> - <i class="fa icon-spin4 animate-spin" v-if="uploading[0]"></i> + <i class="base09 icon-spin4 animate-spin" v-if="uploading[0]"></i> <button class="btn btn-default base05 base02-background" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button> </div> <div class="setting-item"> @@ -35,7 +35,7 @@ <div> <input type="file" @change="uploadFile(1, $event)" ></input> </div> - <i class="fa icon-spin4 animate-spin uploading" v-if="uploading[1]"></i> + <i class="base09 icon-spin4 animate-spin uploading" v-if="uploading[1]"></i> <button class="btn btn-default base05 base02-background" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button> </div> <div class="setting-item"> @@ -46,7 +46,7 @@ <div> <input type="file" @change="uploadFile(2, $event)" ></input> </div> - <i class="fa icon-spin4 animate-spin uploading" v-if="uploading[2]"></i> + <i class="base09 icon-spin4 animate-spin uploading" v-if="uploading[2]"></i> <button class="btn btn-default base05 base02-background" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button> </div> </div> |
