aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS.md5
-rw-r--r--src/App.scss382
-rw-r--r--src/App.vue10
-rw-r--r--src/_variables.scss26
-rw-r--r--src/components/attachment/attachment.js13
-rw-r--r--src/components/attachment/attachment.vue252
-rw-r--r--src/components/chat_panel/chat_panel.js6
-rw-r--r--src/components/chat_panel/chat_panel.vue112
-rw-r--r--src/components/conversation/conversation.vue13
-rw-r--r--src/components/delete_button/delete_button.js2
-rw-r--r--src/components/delete_button/delete_button.vue17
-rw-r--r--src/components/favorite_button/favorite_button.vue29
-rw-r--r--src/components/instance_specific_panel/instance_specific_panel.vue2
-rw-r--r--src/components/login_form/login_form.vue22
-rw-r--r--src/components/media_upload/media_upload.vue4
-rw-r--r--src/components/nav_panel/nav_panel.vue100
-rw-r--r--src/components/notification/notification.js24
-rw-r--r--src/components/notification/notification.vue37
-rw-r--r--src/components/notifications/notifications.js11
-rw-r--r--src/components/notifications/notifications.scss228
-rw-r--r--src/components/notifications/notifications.vue53
-rw-r--r--src/components/post_status_form/post_status_form.js18
-rw-r--r--src/components/post_status_form/post_status_form.vue345
-rw-r--r--src/components/registration/registration.vue27
-rw-r--r--src/components/retweet_button/retweet_button.vue28
-rw-r--r--src/components/settings/settings.js6
-rw-r--r--src/components/settings/settings.vue70
-rw-r--r--src/components/status/status.js44
-rw-r--r--src/components/status/status.vue799
-rw-r--r--src/components/still-image/still-image.js26
-rw-r--r--src/components/still-image/still-image.vue65
-rw-r--r--src/components/style_switcher/style_switcher.js67
-rw-r--r--src/components/style_switcher/style_switcher.vue228
-rw-r--r--src/components/timeline/timeline.js2
-rw-r--r--src/components/timeline/timeline.vue132
-rw-r--r--src/components/user_card/user_card.vue90
-rw-r--r--src/components/user_card_content/user_card_content.js13
-rw-r--r--src/components/user_card_content/user_card_content.vue137
-rw-r--r--src/components/user_finder/user_finder.vue33
-rw-r--r--src/components/user_panel/user_panel.vue12
-rw-r--r--src/components/user_profile/user_profile.vue7
-rw-r--r--src/components/user_settings/user_settings.vue44
-rw-r--r--src/i18n/messages.js424
-rw-r--r--src/modules/statuses.js155
-rw-r--r--src/services/style_setter/style_setter.js79
-rw-r--r--src/services/timeline_fetcher/timeline_fetcher.service.js2
-rw-r--r--static/aurora_borealis.jpgbin0 -> 642707 bytes
-rw-r--r--static/bg2.jpg (renamed from static/bg.jpg)bin229574 -> 229574 bytes
-rw-r--r--static/config.json2
-rw-r--r--static/font/config.json60
-rw-r--r--static/font/css/animation.css7
-rw-r--r--static/font/css/fontello-codes.css10
-rw-r--r--static/font/css/fontello-embedded.css22
-rw-r--r--static/font/css/fontello-ie7-codes.css10
-rw-r--r--static/font/css/fontello-ie7.css10
-rw-r--r--static/font/css/fontello.css24
-rw-r--r--static/font/demo.html65
-rw-r--r--static/font/font/fontello.eotbin9340 -> 12348 bytes
-rw-r--r--static/font/font/fontello.svg22
-rw-r--r--static/font/font/fontello.ttfbin9172 -> 12180 bytes
-rw-r--r--static/font/font/fontello.woffbin5728 -> 7512 bytes
-rw-r--r--static/font/font/fontello.woff2bin4916 -> 6408 bytes
-rw-r--r--static/styles.json14
63 files changed, 2810 insertions, 1637 deletions
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 1bfe3179..3673b8b7 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -4,6 +4,7 @@ Contributors of this project.
- Coco Snuss (cocosnuss@social.heldscal.la): Code
- wakarimasen (wakarimasen@shitposter.club): NSFW hiding image
- dtluna (dtluna@social.heldscal.la): Code
-- sonyam (sonyam@social.heldscal.la): Default background image
+- sonyam (sonyam@social.heldscal.la): Background images
- hakui (hakui@freezepeach.xyz): CSS and styling
-- shpuld (shpuld@shitposter.club): CSS and styling \ No newline at end of file
+- shpuld (shpuld@shitposter.club): CSS and styling
+- Vincent Guth (https://unsplash.com/photos/XrwVIFy6rTw): Background images.
diff --git a/src/App.scss b/src/App.scss
index 95a653ce..a8601220 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -1,10 +1,13 @@
@import './_variables.scss';
+
#app {
- background-size: cover;
- background-attachment: fixed;
- background-repeat: no-repeat;
- background-position: 0 50px;
- min-height: 100vh;
+ background-size: cover;
+ background-attachment: fixed;
+ background-repeat: no-repeat;
+ background-position: 0 50px;
+ min-height: 100vh;
+ max-width: 100%;
+ overflow: hidden;
}
i {
@@ -12,7 +15,7 @@ i {
}
h4 {
- margin: 0;
+ margin: 0;
}
#content {
@@ -26,154 +29,286 @@ h4 {
}
.text-center {
- text-align: center;
+ text-align: center;
}
body {
- font-family: sans-serif;
- font-size: 14px;
- margin: 0;
+ font-family: sans-serif;
+ font-size: 14px;
+ margin: 0;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ max-width: 100vw;
+ overflow-x: hidden;
}
a {
- text-decoration: none;
+ text-decoration: none;
+ color: $fallback--link;
+ color: var(--link, $fallback--link);
}
button{
- user-select: none;
+ user-select: none;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+ border: none;
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+ cursor: pointer;
+ border-top: 1px solid rgba(255, 255, 255, 0.2);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 2px black;
+ font-size: 14px;
+ font-family: sans-serif;
+
+ &:hover {
+ box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ }
+
+ &.pressed {
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg)
+ }
+}
+
+label.select {
+ padding: 0;
+
+}
+
+input, textarea, .select {
+ border: none;
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
+ border-top: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 2px black inset;
+ background-color: $fallback--lightBg;
+ background-color: var(--lightBg, $fallback--lightBg);
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+ font-family: sans-serif;
+ font-size: 14px;
+ padding: 8px 7px;
+ box-sizing: border-box;
+ display: inline-block;
+ position: relative;
+ height: 29px;
+ line-height: 16px;
+
+ .icon-down-open {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 5px;
+ height: 100%;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ line-height: 29px;
+ z-index: 0;
+ pointer-events: none;
+ }
+
+ select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: transparent;
border: none;
- border-radius: 5px;
- cursor: pointer;
- border-top: 1px solid rgba(255, 255, 255, 0.2);
- border-bottom: 1px solid rgba(0, 0, 0, 0.2);
- box-shadow: 0px 0px 2px black;
- font-size: 14px;
- font-family: sans-serif;
-
- &:hover {
- box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
- }
+ margin: 0;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ padding: 4px 2em 3px 3px;
+ width: 100%;
+ z-index: 1;
+ height: 29px;
+ line-height: 16px;
+ }
- &:disabled {
- cursor: not-allowed;
- opacity: 0.5;
+ &[type=radio],
+ &[type=checkbox] {
+ display: none;
+ &:checked + label::before {
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
}
+ + label::before {
+ display: inline-block;
+ content: '✔';
+ transition: color 200ms;
+ width: 1.1em;
+ height: 1.1em;
+ border-radius: $fallback--checkBoxRadius;
+ border-radius: var(--checkBoxRadius, $fallback--checkBoxRadius);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
+ border-top: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 2px black inset;
+ margin-right: .5em;
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+ vertical-align: top;
+ text-align: center;
+ line-height: 1.1em;
+ font-size: 1.1em;
+ box-sizing: border-box;
+ color: transparent;
+ overflow: hidden;
+ box-sizing: border-box;
+ }
+ }
}
+i[class*=icon-] {
+ color: $fallback--icon;
+ color: var(--icon, $fallback--icon)
+}
+
+
.container {
- display: flex;
- flex-wrap: wrap;
- margin: 0;
- padding: 0 10px 0 10px;
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0;
+ padding: 0 10px 0 10px;
}
.gaps {
- margin: -1em 0 0 -1em;
+ margin: -1em 0 0 -1em;
}
.item {
- flex: 1;
- line-height: 21px;
- height: 21px;
- overflow: hidden;
+ flex: 1;
+ line-height: 50px;
+ height: 50px;
+ overflow: hidden;
- .nav-icon {
- font-size: 1.1em;
- margin-left: 0.4em;
- }
+ .nav-icon {
+ font-size: 1.1em;
+ margin-left: 0.4em;
+ }
}
.gaps > .item {
- padding: 1em 0 0 1em;
+ padding: 1em 0 0 1em;
}
.auto-size {
- flex: 1
+ flex: 1
}
nav {
- width: 100%;
+ width: 100%;
+ align-items: center;
+ position: fixed;
+ height: 50px;
+
+ .inner-nav {
+ padding-left: 20px;
+ padding-right: 20px;
+ display: flex;
align-items: center;
- position: fixed;
+ flex-basis: 970px;
+ margin: auto;
height: 50px;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: auto 80%;
- .inner-nav {
- padding-left: 20px;
- padding-right: 20px;
- display: flex;
- align-items: center;
- flex-basis: 970px;
- margin: auto;
- height: 50px;
- background-repeat: no-repeat;
- background-position: center;
- background-size: contain;
+ a i {
+ color: $fallback--link;
+ color: var(--link, $fallback--link);
}
+ }
}
main-router {
- flex: 1;
+ flex: 1;
}
.status.compact {
- color: rgba(0, 0, 0, 0.42);
- font-weight: 300;
+ color: rgba(0, 0, 0, 0.42);
+ font-weight: 300;
- p {
- margin: 0;
- font-size: 0.8em
- }
+ p {
+ margin: 0;
+ font-size: 0.8em
+ }
}
/* Panel */
.panel {
- display: flex;
- flex-direction: column;
- margin: 0.5em;
+ display: flex;
+ flex-direction: column;
+ margin: 0.5em;
- border-radius: 10px;
- box-shadow: 1px 1px 4px rgba(0,0,0,.6);
- overflow: hidden;
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+
+ border-radius: $fallback--panelRadius;
+ border-radius: var(--panelRadius, $fallback--panelRadius);
+ box-shadow: 1px 1px 4px rgba(0,0,0,.6);
}
.panel-body:empty::before {
- content: "¯\\_(ツ)_/¯"; // Could use words but it'd require translations
- display: block;
- margin: 1em;
- text-align: center;
+ content: "¯\\_(ツ)_/¯"; // Could use words but it'd require translations
+ display: block;
+ margin: 1em;
+ text-align: center;
}
.panel-heading {
- border-radius: 10px 10px 0 0;
- background-size: cover;
- padding: 0.6em 1.0em;
- text-align: left;
- font-size: 1.3em;
- line-height: 24px;
+ border-radius: $fallback--panelRadius $fallback--panelRadius 0 0;
+ border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0;
+ background-size: cover;
+ padding: 0.6em 1.0em;
+ text-align: left;
+ font-size: 1.3em;
+ line-height: 24px;
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+}
+
+.panel-heading.stub {
+ border-radius: $fallback--panelRadius;
+ border-radius: var(--panelRadius, $fallback--panelRadius);
}
.panel-footer {
- border-radius: 0 0 10px 10px;
+ border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
+ border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
}
.panel-body > p {
- line-height: 18px;
- padding: 1em;
- margin: 0;
+ line-height: 18px;
+ padding: 1em;
+ margin: 0;
}
.container > * {
- min-width: 0px;
+ min-width: 0px;
}
.fa {
- color: grey;
+ color: grey;
}
nav {
- z-index: 1000;
- box-shadow: 0px 0px 4px rgba(0,0,0,.6);
+ z-index: 1000;
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ box-shadow: 0px 0px 4px rgba(0,0,0,.6);
}
.fade-enter-active, .fade-leave-active {
@@ -184,9 +319,9 @@ nav {
}
.main {
- flex-basis: 60%;
- flex-grow: 1;
- flex-shrink: 1;
+ flex-basis: 60%;
+ flex-grow: 1;
+ flex-shrink: 1;
}
.sidebar-bounds {
@@ -201,20 +336,20 @@ nav {
}
.mobile-shown {
- display: none;
+ display: none;
}
.panel-switcher {
- display: none;
- width: 100%;
- height: 46px;
- button {
- display: block;
- flex: 1;
- max-height: 32px;
- margin: 0.5em;
- padding: 0.5em;
- }
+ display: none;
+ width: 100%;
+ height: 46px;
+ button {
+ display: block;
+ flex: 1;
+ max-height: 32px;
+ margin: 0.5em;
+ padding: 0.5em;
+ }
}
@media all and (min-width: 960px) {
@@ -248,25 +383,46 @@ nav {
}
}
+.alert {
+ margin: 0.35em;
+ padding: 0.25em;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ min-height: 28px;
+ line-height: 28px;
+
+ &.error {
+ background-color: $fallback--cAlertRed;
+ background-color: var(--cAlertRed, $fallback--cAlertRed);
+ }
+}
+
+.faint {
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+}
+
@media all and (max-width: 959px) {
- .mobile-hidden {
- display: none;
- }
+ .mobile-hidden {
+ display: none;
+ }
- .panel-switcher {
- display: flex;
- }
+ .panel-switcher {
+ display: flex;
+ }
- .container {
- padding: 0 0 0 0;
- }
+ .container {
+ padding: 0 0 0 0;
+ }
- .panel {
- margin: 0.5em 0 0.5em 0;
- }
+ .panel {
+ margin: 0.5em 0 0.5em 0;
+ }
}
.item.right {
- text-align: right;
- padding-right: 20px;
+ text-align: right;
+ padding-right: 20px;
}
diff --git a/src/App.vue b/src/App.vue
index 1d8dd6c8..923d411b 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,6 +1,6 @@
<template>
- <div id="app" v-bind:style="style" class="base02-background">
- <nav class='container base02-background base05' @click="scrollToTop()" id="nav">
+ <div id="app" v-bind:style="style">
+ <nav class='container' @click="scrollToTop()" id="nav">
<div class='inner-nav' :style="logoStyle">
<div class='item'>
<router-link :to="{ name: 'root'}">{{sitename}}</router-link>
@@ -14,8 +14,8 @@
</nav>
<div class="container" id="content">
<div class="panel-switcher">
- <button @click="activatePanel('sidebar')" class="base02-background base05">Sidebar</button>
- <button @click="activatePanel('timeline')" class="base02-background base05">Timeline</button>
+ <button @click="activatePanel('sidebar')">Sidebar</button>
+ <button @click="activatePanel('timeline')">Timeline</button>
</div>
<div class="sidebar-flexer" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar'}">
<div class="sidebar-bounds">
@@ -25,7 +25,6 @@
<nav-panel></nav-panel>
<instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel>
<who-to-follow-panel v-if="currentUser && showWhoToFollowPanel"></who-to-follow-panel>
- <chat-panel v-if="currentUser && chat"></chat-panel>
<notifications v-if="currentUser"></notifications>
</div>
</div>
@@ -37,6 +36,7 @@
</transition>
</div>
</div>
+ <chat-panel v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
</div>
</template>
diff --git a/src/_variables.scss b/src/_variables.scss
index d2b7065d..d90a1d48 100644
--- a/src/_variables.scss
+++ b/src/_variables.scss
@@ -1,7 +1,27 @@
$main-color: #f58d2c;
$main-background: white;
$darkened-background: whitesmoke;
-$green: #0fa00f;
-$blue: #0095ff;
-$red: #ff0000;
+$fallback--bg: #121a24;
+$fallback--btn: #182230;
+$fallback--faint: #999;
+$fallback--fg: #b9b9ba;
+$fallback--link: #d8a070;
+$fallback--icon: #666;
+$fallback--lightBg: rgb(21, 30, 42);
+$fallback--lightFg: #b9b9ba;
+$fallback--border: #222;
+$fallback--cRed: #ff0000;
+$fallback--cBlue: #0095ff;
+$fallback--cGreen: #0fa00f;
+$fallback--cOrange: orange;
+
+$fallback--cAlertRed: rgba(211,16,20,.5);
+
+$fallback--panelRadius: 10px;
+$fallback--checkBoxRadius: 2px;
+$fallback--btnRadius: 4px;
+$fallback--tooltipRadius: 5px;
+$fallback--avatarRadius: 4px;
+$fallback--avatarAltRadius: 10px;
+$fallback--attachmentRadius: 10px;
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js
index 8a2a3826..d9bc4477 100644
--- a/src/components/attachment/attachment.js
+++ b/src/components/attachment/attachment.js
@@ -1,3 +1,4 @@
+import StillImage from '../still-image/still-image.vue'
import nsfwImage from '../../assets/nsfw.png'
import fileTypeService from '../../services/file_type/file_type.service.js'
@@ -5,7 +6,8 @@ const Attachment = {
props: [
'attachment',
'nsfw',
- 'statusId'
+ 'statusId',
+ 'size'
],
data () {
return {
@@ -16,6 +18,9 @@ const Attachment = {
img: document.createElement('img')
}
},
+ components: {
+ StillImage
+ },
computed: {
type () {
return fileTypeService.fileType(this.attachment.mimetype)
@@ -25,6 +30,12 @@ const Attachment = {
},
isEmpty () {
return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown'
+ },
+ isSmall () {
+ return this.size === 'small'
+ },
+ fullwidth () {
+ return fileTypeService.fileType(this.attachment.mimetype) === 'html'
}
},
methods: {
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index d6a51ffd..b2f63668 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -1,5 +1,8 @@
<template>
- <div class="attachment base03-border" :class="{[type]: true, loading}" v-show="!isEmpty">
+ <div v-if="size==='hide'">
+ <a class="placeholder" v-if="type !== 'html'" target="_blank" :href="attachment.url">[{{nsfw ? "NSFW/" : ""}}{{type.toUpperCase()}}]</a>
+ </div>
+ <div v-else class="attachment" :class="{[type]: true, loading, 'small-attachment': isSmall, 'fullwidth': fullwidth}" v-show="!isEmpty">
<a class="image-attachment" v-if="hidden" @click.prevent="toggleHidden()">
<img :key="nsfwImage" :src="nsfwImage"/>
</a>
@@ -8,10 +11,10 @@
</div>
<a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank">
- <img class="base03-border" referrerpolicy="no-referrer" :src="attachment.large_thumb_url || attachment.url"/>
+ <StillImage :class="{'small': isSmall}" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
</a>
- <video class="base03" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video>
+ <video :class="{'small': isSmall}" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video>
<audio v-if="type === 'audio'" :src="attachment.url" controls></audio>
@@ -30,110 +33,145 @@
<script src="./attachment.js"></script>
<style lang="scss">
- .attachments {
- display: flex;
- flex-wrap: wrap;
- margin-right: -0.7em;
-
- .attachment.media-upload-container {
- flex: 0 0 auto;
- max-height: 300px;
- max-width: 100%;
+@import '../../_variables.scss';
+
+.attachments {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -0.7em;
+
+ .attachment.media-upload-container {
+ flex: 0 0 auto;
+ max-height: 300px;
+ max-width: 100%;
+ }
+
+ .placeholder {
+ margin-right: 0.5em;
+ }
+
+ .small-attachment {
+ &.image, &.video {
+ max-width: 35%;
+ }
+ max-height: 100px;
+ }
+
+ .attachment {
+ flex: 1 0 30%;
+ margin: 0.5em 0.7em 0.6em 0.0em;
+ align-self: flex-start;
+ line-height: 0;
+
+ border-style: solid;
+ border-width: 1px;
+ border-radius: $fallback--attachmentRadius;
+ border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ overflow: hidden;
+ }
+ .fullwidth {
+ flex-basis: 100%;
+ }
+ // fixes small gap below video
+ &.video {
+ line-height: 0;
+ }
+
+ &.html {
+ flex-basis: 90%;
+ width: 100%;
+ display: flex;
+ }
+
+ &.loading {
+ cursor: progress;
+ }
+
+ .hider {
+ position: absolute;
+ margin: 10px;
+ padding: 5px;
+ background: rgba(230,230,230,0.6);
+ font-weight: bold;
+ z-index: 4;
+ }
+
+ .small {
+ max-height: 100px;
+ }
+ video {
+ max-height: 500px;
+ height: 100%;
+ width: 100%;
+ z-index: 0;
+ }
+
+ audio {
+ width: 100%;
+ }
+
+ img.media-upload {
+ line-height: 0;
+ max-height: 300px;
+ max-width: 100%;
+ }
+
+ .oembed {
+ line-height: 1.2em;
+ flex: 1 0 100%;
+ width: 100%;
+ margin-right: 15px;
+ display: flex;
+
+ img {
+ width: 100%;
+ }
+
+ .image {
+ flex: 1;
+ img {
+ border: 0px;
+ border-radius: 5px;
+ height: 100%;
+ object-fit: cover;
+ }
+ }
+
+ .text {
+ flex: 2;
+ margin: 8px;
+ word-break: break-all;
+ h1 {
+ font-size: 14px;
+ margin: 0px;
}
-
- .attachment {
- flex: 1 0 30%;
- margin: 0.5em 0.7em 0.6em 0.0em;
- align-self: flex-start;
-
- border-style: solid;
- border-width: 1px;
- border-radius: 5px;
- overflow: hidden;
-
- // fixes small gap below video
- &.video {
- line-height: 0;
- }
-
- &.html {
- flex-basis: 90%;
- width: 100%;
- display: flex;
- }
-
- &.loading {
- cursor: progress;
- }
-
- .hider {
- position: absolute;
- margin: 10px;
- padding: 5px;
- background: rgba(230,230,230,0.6);
- font-weight: bold;
- z-index: 4;
- }
-
- video {
- max-height: 500px;
- height: 100%;
- width: 100%;
- z-index: 0;
- }
-
- audio {
- width: 100%;
- }
-
- img.media-upload {
- margin-bottom: -2px;
- max-height: 300px;
- max-width: 100%;
- }
-
- .oembed {
- width: 100%;
- margin-right: 15px;
- display: flex;
-
- img {
- width: 100%;
- }
-
- .image {
- flex: 1;
- img {
- border: 0px;
- border-radius: 5px;
- height: 100%;
- object-fit: cover;
- }
- }
-
- .text {
- flex: 2;
- margin: 8px;
- word-break: break-all;
- h1 {
- font-size: 14px;
- margin: 0px;
- }
- }
- }
-
- a.image-attachment {
- display: flex;
- flex: 1;
-
- img {
- object-fit: contain;
- width: 100%;
- height: 100%; /* If this isn't here, chrome will stretch the images */
- max-height: 500px;
- image-orientation: from-image;
- }
- }
+ }
+ }
+
+ .image-attachment {
+ display: flex;
+ flex: 1;
+
+ .still-image {
+ width: 100%;
+ height: 100%;
+ }
+
+ .small {
+ img {
+ max-height: 100px;
}
- }
+ }
+
+ img {
+ object-fit: contain;
+ width: 100%;
+ height: 100%; /* If this isn't here, chrome will stretch the images */
+ max-height: 500px;
+ image-orientation: from-image;
+ }
+ }
+}
</style>
diff --git a/src/components/chat_panel/chat_panel.js b/src/components/chat_panel/chat_panel.js
index b146c5d9..d528d0a1 100644
--- a/src/components/chat_panel/chat_panel.js
+++ b/src/components/chat_panel/chat_panel.js
@@ -2,7 +2,8 @@ const chatPanel = {
data () {
return {
currentMessage: '',
- channel: null
+ channel: null,
+ collapsed: false
}
},
computed: {
@@ -14,6 +15,9 @@ const chatPanel = {
submit (message) {
this.$store.state.chat.channel.push('new_msg', {text: message}, 10000)
this.currentMessage = ''
+ },
+ togglePanel () {
+ this.collapsed = !this.collapsed
}
}
}
diff --git a/src/components/chat_panel/chat_panel.vue b/src/components/chat_panel/chat_panel.vue
index ec379db5..30070d3e 100644
--- a/src/components/chat_panel/chat_panel.vue
+++ b/src/components/chat_panel/chat_panel.vue
@@ -1,26 +1,40 @@
<template>
- <div class="chat-panel">
- <div class="panel panel-default base01-background">
- <div class="panel-heading timeline-heading base02-background base04">
+ <div class="chat-panel" v-if="!this.collapsed">
+ <div class="panel panel-default">
+ <div class="panel-heading timeline-heading chat-heading" @click.stop.prevent="togglePanel">
<div class="title">
{{$t('chat.title')}}
+ <i class="icon-cancel" style="float: right;"></i>
</div>
</div>
<div class="chat-window" v-chat-scroll>
<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 class="chat-content">
+ <router-link class="chat-name" :to="{ name: 'user-profile', params: { id: message.author.id } }">
+ {{message.author.username}}
+ </router-link>
+ <br>
+ <span class="chat-text">
+ {{message.text}}
+ </span>
+ </div>
</div>
</div>
<div class="chat-input">
- <form @submit.prevent="submit(currentMessage)">
- <input v-model="currentMessage" type="text" >
- </form>
+ <textarea @keyup.enter="submit(currentMessage)" v-model="currentMessage" class="chat-input-textarea" rows="1"></textarea>
+ </div>
+ </div>
+ </div>
+ <div v-else class="chat-panel">
+ <div class="panel panel-default">
+ <div class="panel-heading stub timeline-heading chat-heading" @click.stop.prevent="togglePanel">
+ <div class="title">
+ <i class="icon-comment-empty"></i>
+ {{$t('chat.title')}}
+ </div>
</div>
</div>
</div>
@@ -29,30 +43,56 @@
<script src="./chat_panel.js"></script>
<style lang="scss">
- .chat-window {
- max-height: 200px;
- 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;
- }
- }
- }
+@import '../../_variables.scss';
+
+.floating-chat {
+ position: fixed;
+ right: 0px;
+ bottom: 0px;
+ z-index: 1000;
+}
+
+.chat-heading {
+ cursor: pointer;
+ .icon-comment-empty {
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ }
+}
+
+.chat-window {
+ width: 345px;
+ max-height: 40vh;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.chat-name {
+}
+
+.chat-message {
+ display: flex;
+ padding: 0.2em 0.5em
+}
+
+.chat-avatar {
+ img {
+ height: 24px;
+ width: 24px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ margin-right: 0.5em;
+ margin-top: 0.25em;
+ }
+}
+
+.chat-input {
+ display: flex;
+ textarea {
+ flex: 1;
+ margin: 0.6em;
+ min-height: 3.5em;
+ resize: none;
+ }
+}
</style>
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 60d43fff..308e5e7d 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -1,6 +1,6 @@
<template>
<div class="timeline panel panel-default">
- <div class="panel-heading base02-background base04 base03-border conversation-heading">
+ <div class="panel-heading conversation-heading">
{{ $t('timeline.conversation') }}
<span v-if="collapsable" style="float:right;">
<small><a href="#" @click.prevent="$emit('toggleExpanded')">Collapse</a></small>
@@ -8,7 +8,16 @@
</div>
<div class="panel-body">
<div class="timeline">
- <status v-for="status in conversation" @goto="setHighlight" :key="status.id" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true' :highlight="highlight" :replies="getReplies(status.id)"></status>
+ <status
+ v-for="status in conversation"
+ @goto="setHighlight" :key="status.id"
+ :inlineExpanded="collapsable" :statusoid="status"
+ :expandable='false' :focused="focused(status.id)"
+ :inConversation='true'
+ :highlight="highlight"
+ :replies="getReplies(status.id)"
+ class="status-fadein">
+ </status>
</div>
</div>
</div>
diff --git a/src/components/delete_button/delete_button.js b/src/components/delete_button/delete_button.js
index 77da1b87..f2920666 100644
--- a/src/components/delete_button/delete_button.js
+++ b/src/components/delete_button/delete_button.js
@@ -10,7 +10,7 @@ const DeleteButton = {
},
computed: {
currentUser () { return this.$store.state.users.currentUser },
- canDelete () { return this.currentUser.rights.delete_others_notice || this.status.user.id === this.currentUser.id }
+ canDelete () { return this.currentUser && this.currentUser.rights.delete_others_notice || this.status.user.id === this.currentUser.id }
}
}
diff --git a/src/components/delete_button/delete_button.vue b/src/components/delete_button/delete_button.vue
index 845ac777..d13547e2 100644
--- a/src/components/delete_button/delete_button.vue
+++ b/src/components/delete_button/delete_button.vue
@@ -1,20 +1,21 @@
<template>
<div v-if="canDelete">
<a href="#" v-on:click.prevent="deleteStatus()">
- <i class='base09 icon-cancel delete-status'></i>
+ <i class='icon-cancel delete-status'></i>
</a>
</div>
</template>
<script src="./delete_button.js" ></script>
-<style lang='scss'>
- @import '../../_variables.scss';
+<style lang="scss">
+@import '../../_variables.scss';
- .icon-cancel,.delete-status {
- cursor: pointer;
- &:hover {
- color: $red;
- }
+.icon-cancel,.delete-status {
+ cursor: pointer;
+ &:hover {
+ color: var(--cRed, $fallback--cRed);
+ color: $fallback--cRed;
}
+}
</style>
diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue
index 65d368c7..1e1a6970 100644
--- a/src/components/favorite_button/favorite_button.vue
+++ b/src/components/favorite_button/favorite_button.vue
@@ -1,26 +1,31 @@
<template>
<div v-if="loggedIn">
- <i :class='classes' class='favorite-button fav-active base09' @click.prevent='favorite()'/>
+ <i :class='classes' class='favorite-button fav-active' @click.prevent='favorite()'/>
<span v-if='status.fave_num > 0'>{{status.fave_num}}</span>
</div>
<div v-else>
- <i :class='classes' class='favorite-button base09'/>
+ <i :class='classes' class='favorite-button'/>
<span v-if='status.fave_num > 0'>{{status.fave_num}}</span>
</div>
</template>
<script src="./favorite_button.js" ></script>
-<style lang='scss'>
- .fav-active {
- cursor: pointer;
- animation-duration: 0.6s;
- &:hover {
- color: orange;
- }
- }
- .favorite-button.icon-star {
- color: orange;
+<style lang="scss">
+@import '../../_variables.scss';
+
+.fav-active {
+ cursor: pointer;
+ animation-duration: 0.6s;
+
+ &:hover {
+ color: $fallback--cOrange;
+ color: var(--cOrange, $fallback--cOrange);
}
+}
+.favorite-button.icon-star {
+ color: $fallback--cOrange;
+ color: var(--cOrange, $fallback--cOrange);
+}
</style>
diff --git a/src/components/instance_specific_panel/instance_specific_panel.vue b/src/components/instance_specific_panel/instance_specific_panel.vue
index b3ea019d..ca8e00c0 100644
--- a/src/components/instance_specific_panel/instance_specific_panel.vue
+++ b/src/components/instance_specific_panel/instance_specific_panel.vue
@@ -1,6 +1,6 @@
<template>
<div class="instance-specific-panel">
- <div class="panel panel-default base01-background">
+ <div class="panel panel-default">
<div class="panel-body">
<div v-html="instanceSpecificPanelContent">
</div>
diff --git a/src/components/login_form/login_form.vue b/src/components/login_form/login_form.vue
index c293d611..67fa95a8 100644
--- a/src/components/login_form/login_form.vue
+++ b/src/components/login_form/login_form.vue
@@ -1,7 +1,7 @@
<template>
- <div class="login panel panel-default base00-background">
+ <div class="login panel panel-default">
<!-- Default panel contents -->
- <div class="panel-heading base02-background base04">
+ <div class="panel-heading">
{{$t('login.login')}}
</div>
<div class="panel-body">
@@ -17,11 +17,11 @@
<div class='form-group'>
<div class='login-bottom'>
<div><router-link :to="{name: 'registration'}" v-if='registrationOpen' class='register'>{{$t('login.register')}}</router-link></div>
- <button :disabled="loggingIn" type='submit' class='btn btn-default base04 base02-background'>{{$t('login.login')}}</button>
+ <button :disabled="loggingIn" type='submit' class='btn btn-default'>{{$t('login.login')}}</button>
</div>
</div>
<div v-if="authError" class='form-group'>
- <div class='error base05'>{{authError}}</div>
+ <div class='alert error'>{{authError}}</div>
</div>
</form>
</div>
@@ -31,27 +31,16 @@
<script src="./login_form.js" ></script>
<style lang="scss">
+@import '../../_variables.scss';
.login-form {
- input {
- border-width: 1px;
- border-style: solid;
- border-color: silver;
- border-radius: 5px;
- padding: 0.1em 0.2em 0.2em 0.2em;
- }
-
.btn {
min-height: 28px;
width: 10em;
}
.error {
- border-radius: 5px;
text-align: center;
- background-color: rgba(255, 48, 16, 0.65);
- min-height: 28px;
- line-height: 28px;
}
.register {
@@ -66,5 +55,4 @@
justify-content: space-between;
}
}
-
</style>
diff --git a/src/components/media_upload/media_upload.vue b/src/components/media_upload/media_upload.vue
index 9e6ad608..8b931d2d 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="base09 icon-spin4 animate-spin" v-if="uploading"></i>
- <i class="base09 icon-upload" v-if="!uploading"></i>
+ <i class="icon-spin4 animate-spin" v-if="uploading"></i>
+ <i class="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.vue b/src/components/nav_panel/nav_panel.vue
index aea841e9..6f949afb 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -1,24 +1,24 @@
<template>
<div class="nav-panel">
- <div class="panel panel-default base01-background">
- <ul class="base03-border">
+ <div class="panel panel-default">
+ <ul>
<li v-if='currentUser'>
- <router-link class="base00-background" to='/main/friends'>
+ <router-link to='/main/friends'>
{{ $t("nav.timeline") }}
</router-link>
</li>
<li v-if='currentUser'>
- <router-link class="base00-background" :to="{ name: 'mentions', params: { username: currentUser.screen_name } }">
+ <router-link :to="{ name: 'mentions', params: { username: currentUser.screen_name } }">
{{ $t("nav.mentions") }}
</router-link>
</li>
<li>
- <router-link class="base00-background" to='/main/public'>
+ <router-link to='/main/public'>
{{ $t("nav.public_tl") }}
</router-link>
</li>
<li>
- <router-link class="base00-background" to='/main/all'>
+ <router-link to='/main/all'>
{{ $t("nav.twkn") }}
</router-link>
</li>
@@ -30,43 +30,61 @@
<script src="./nav_panel.js" ></script>
<style lang="scss">
- .nav-panel ul {
- list-style: none;
- margin: 0;
- padding: 0;
- }
+@import '../../_variables.scss';
- .nav-panel li {
- border-bottom: 1px solid;
- border-color: inherit;
- padding: 0;
- &:first-child a {
- border-top-right-radius: 10px;
- border-top-left-radius: 10px;
- }
- &:last-child a {
- border-bottom-right-radius: 10px;
- border-bottom-left-radius: 10px;
- }
- }
+.nav-panel .panel {
+ overflow: hidden;
+}
+.nav-panel ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
- .nav-panel li:last-child {
- border: none;
- }
+.nav-panel li {
+ border-bottom: 1px solid;
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+ padding: 0;
- .nav-panel a {
- display: block;
- padding: 0.8em 0.85em;
- &:hover {
- background-color: transparent;
- }
- &.router-link-active {
- font-weight: bolder;
- background-color: transparent;
- &:hover {
- text-decoration: underline;
- }
- }
- }
+ &:first-child a {
+ border-top-right-radius: $fallback--panelRadius;
+ border-top-right-radius: var(--panelRadius, $fallback--panelRadius);
+ border-top-left-radius: $fallback--panelRadius;
+ border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
+ }
+ &:last-child a {
+ border-bottom-right-radius: $fallback--panelRadius;
+ border-bottom-right-radius: var(--panelRadius, $fallback--panelRadius);
+ border-bottom-left-radius: $fallback--panelRadius;
+ border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius);
+ }
+}
+
+.nav-panel li:last-child {
+ border: none;
+}
+
+.nav-panel a {
+ display: block;
+ padding: 0.8em 0.85em;
+
+ &:hover {
+ background-color: $fallback--lightBg;
+ background-color: var(--lightBg, $fallback--lightBg);
+ }
+
+ &.router-link-active {
+ font-weight: bolder;
+ background-color: $fallback--lightBg;
+ background-color: var(--lightBg, $fallback--lightBg);
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+}
</style>
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
new file mode 100644
index 00000000..3a274374
--- /dev/null
+++ b/src/components/notification/notification.js
@@ -0,0 +1,24 @@
+import Status from '../status/status.vue'
+import StillImage from '../still-image/still-image.vue'
+import UserCardContent from '../user_card_content/user_card_content.vue'
+
+const Notification = {
+ data () {
+ return {
+ userExpanded: false
+ }
+ },
+ props: [
+ 'notification'
+ ],
+ components: {
+ Status, StillImage, UserCardContent
+ },
+ methods: {
+ toggleUserExpanded () {
+ this.userExpanded = !this.userExpanded
+ }
+ }
+}
+
+export default Notification
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
new file mode 100644
index 00000000..eed598a8
--- /dev/null
+++ b/src/components/notification/notification.vue
@@ -0,0 +1,37 @@
+<template>
+ <status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
+ <div class="non-mention" v-else>
+ <a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
+ <StillImage class='avatar-compact' :src="notification.action.user.profile_image_url_original"/>
+ </a>
+ <div class='notification-right'>
+ <div class="usercard notification-usercard" v-if="userExpanded">
+ <user-card-content :user="notification.action.user" :switcher="false"></user-card-content>
+ </div>
+ <span class="notification-details">
+ <div class="name-and-action">
+ <span class="username" :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
+ <span v-if="notification.type === 'favorite'">
+ <i class="fa icon-star lit"></i>
+ <small>{{$t('notifications.favorited_you')}}</small>
+ </span>
+ <span v-if="notification.type === 'repeat'">
+ <i class="fa icon-retweet lit"></i>
+ <small>{{$t('notifications.repeated_you')}}</small>
+ </span>
+ <span v-if="notification.type === 'follow'">
+ <i class="fa icon-user-plus lit"></i>
+ <small>{{$t('notifications.followed_you')}}</small>
+ </span>
+ </div>
+ <small class="timeago"><router-link :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small>
+ </span>
+ <div class="follow-text" v-if="notification.type === 'follow'">
+ <router-link :to="{ name: 'user-profile', params: { id: notification.action.user.id } }">@{{notification.action.user.screen_name}}</router-link>
+ </div>
+ <status v-else class="faint" :compact="true" :statusoid="notification.status" :noHeading="true"></status>
+ </div>
+ </div>
+</template>
+
+<script src="./notification.js"></script>
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index 5f0d7f26..f8314bfc 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -1,11 +1,11 @@
-import Status from '../status/status.vue'
+import Notification from '../notification/notification.vue'
import { sortBy, take, filter } from 'lodash'
const Notifications = {
data () {
return {
- visibleNotificationCount: 10
+ visibleNotificationCount: 20
}
},
computed: {
@@ -23,15 +23,10 @@ const Notifications = {
},
unseenCount () {
return this.unseenNotifications.length
- },
- hiderStyle () {
- return {
- background: `linear-gradient(to bottom, rgba(0, 0, 0, 0), ${this.$store.state.config.colors['base00']} 80%)`
- }
}
},
components: {
- Status
+ Notification
},
watch: {
unseenCount (count) {
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 241f10b4..9cbb1226 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -4,10 +4,24 @@
// a bit of a hack to allow scrolling below notifications
padding-bottom: 15em;
+ .panel {
+ background: $fallback--bg;
+ background: var(--bg, $fallback--bg)
+ }
+
+ .panel-body {
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border)
+ }
+
.panel-heading {
// force the text to stay centered, while keeping
// the button in the right side of the panel heading
position: relative;
+ background: $fallback--btn;
+ background: var(--btn, $fallback--btn);
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
.read-button {
position: absolute;
right: 0.7em;
@@ -18,7 +32,8 @@
.unseen-count {
display: inline-block;
- background-color: rgba(255, 16, 8, 0.8);
+ background-color: $fallback--cRed;
+ background-color: var(--cRed, $fallback--cRed);
text-shadow: 0px 0px 3px rgba(0, 0, 0, 0.5);
min-width: 1.3em;
border-radius: 1.3em;
@@ -29,92 +44,167 @@
line-height: 1.3em;
}
- .notification {
- // Will have to use pixels here to ensure consistent distance with
- // pad alone and pad + border, browsers bad at rounding this with em,
- // they love to give a 1 pixel ghost offset with 0.7em vs 0.3em + 0.4em,
- // which does not happen with 10px vs 4px + 6px.
- padding: 0.4em 0 0 10px;
- display: flex;
- border-bottom: 1px solid;
- border-bottom-color: inherit;
+ .unseen {
+ border-left: 4px solid $fallback--cRed;
+ border-left: 4px solid var(--cRed, $fallback--cRed);
+ padding-left: 0;
+ }
+}
+.notification {
+ box-sizing: border-box;
+ display: flex;
+ border-bottom: 1px solid;
+ border-bottom-color: inherit;
+ padding-left: 4px;
+
+ .avatar-compact {
+ width: 32px;
+ height: 32px;
+ border-radius: $fallback--avatarAltRadius;
+ border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+ overflow: hidden;
+ line-height: 0;
+
+ &.animated::before {
+ display: none;
+ }
+ }
- .text {
- min-width: 0px;
- word-wrap: break-word;
- line-height:18px;
- position: relative;
- overflow: hidden;
+ &:hover .animated.avatar {
+ canvas {
+ display: none;
+ }
+ img {
+ visibility: visible;
+ }
+ }
- .icon-retweet.lit {
- color: $green;
- }
+ .notification-usercard {
+ margin: 0;
+ }
- .icon-user-plus.lit {
- color: $blue;
+ .non-mention {
+ display: flex;
+ flex: 1;
+ flex-wrap: nowrap;
+ padding: 0.6em;
+ min-width: 0;
+ .avatar-container {
+ width: 32px;
+ height: 32px;
+ }
+ .status-el {
+ .status {
+ padding: 0.25em 0;
+ color: $fallback--faint;
+ color: var($fallback--faint, --faint);
}
-
- .icon-reply.lit {
- color: $blue;
+ padding: 0;
+ .media-body {
+ margin: 0;
}
+ }
+ }
- .icon-star.lit {
- color: orange;
- }
+ .follow-text {
+ padding: 0.5em 0;
+ }
- .status-content {
- margin: 0;
- max-height: 300px;
- }
+ .status-el {
+ flex: 1;
+ }
- h1 {
- word-break: break-all;
- margin: 0 0 0.3em;
- padding: 0;
- font-size: 1em;
- line-height:20px;
- small {
- font-weight: lighter;
- }
- }
+ time {
+ white-space: nowrap;
+ }
- padding: 0.3em 0.8em 0.5em;
- p {
- margin: 0;
- margin-top: 0;
- margin-bottom: 0.3em;
- }
+ .notification-right {
+ flex: 1;
+ padding-left: 0.8em;
+ min-width: 0;
+ }
+
+ .notification-details {
+ min-width: 0px;
+ word-wrap: break-word;
+ line-height:18px;
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+ flex: 1 1 0;
+ display: flex;
+ flex-wrap: nowrap;
+
+ .name-and-action {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
- .avatar {
- padding-top: 0.3em;
- width: 32px;
- height: 32px;
- border-radius: 50%;
+ .username {
+ font-weight: bolder;
+ max-width: 100%;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .timeago {
+ float: right;
+ font-size: 12px;
}
- &:last-child {
- border-bottom: none;
- border-radius: 0 0 10px 10px;
+ .icon-retweet.lit {
+ color: $fallback--cGreen;
+ color: var(--cGreen, $fallback--cGreen);
}
- }
- .notification-content {
- max-height: 12em;
- overflow-y: hidden;
- //text-overflow: ellipsis;
- }
+ .icon-user-plus.lit {
+ color: $fallback--cBlue;
+ color: var(--cBlue, $fallback--cBlue);
+ }
- .notification-gradient {
- position: absolute;
- width: 100%;
- height: 4em;
- margin-top:8em;
+ .icon-reply.lit {
+ color: $fallback--cBlue;
+ color: var(--cBlue, $fallback--cBlue);
+ }
+
+ .icon-star.lit {
+ color: orange;
+ color: $fallback--cOrange;
+ color: var(--cOrange, $fallback--cOrange);
+ }
+
+ .status-content {
+ margin: 0;
+ max-height: 300px;
+ }
+
+ h1 {
+ word-break: break-all;
+ margin: 0 0 0.3em;
+ padding: 0;
+ font-size: 1em;
+ line-height:20px;
+ small {
+ font-weight: lighter;
+ }
+ }
+
+ p {
+ margin: 0;
+ margin-top: 0;
+ margin-bottom: 0.3em;
+ }
}
- .unseen {
- border-left: 4px solid rgba(255, 16, 8, 0.75);
- padding-left: 6px;
+ // ugly as heck
+ &:last-child {
+ border-bottom: none;
+ border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
+ border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
+ .status-el {
+ border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
+ border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
+ }
}
}
diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue
index b341fcef..4fa6e925 100644
--- a/src/components/notifications/notifications.vue
+++ b/src/components/notifications/notifications.vue
@@ -1,55 +1,14 @@
<template>
<div class="notifications">
- <div class="panel panel-default base00-background">
- <div class="panel-heading base02-background base04">
+ <div class="panel panel-default">
+ <div class="panel-heading">
<span class="unseen-count" v-if="unseenCount">{{unseenCount}}</span>
{{$t('notifications.notifications')}}
- <button v-if="unseenCount" @click.prevent="markAsSeen" class="base04 base02-background read-button">{{$t('notifications.read')}}</button>
+ <button v-if="unseenCount" @click.prevent="markAsSeen" class="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}'>
- <div>
- <a :href="notification.action.user.statusnet_profile_url" target="_blank">
- <img class='avatar' :src="notification.action.user.profile_image_url_original">
- </a>
- </div>
- <div class='text' style="width: 100%;">
- <div v-if="notification.type === 'favorite'">
- <h1>
- <span :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
- <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>
- <div class="notification-content" v-html="notification.status.statusnet_html"></div>
- </div>
- <div v-if="notification.type === 'repeat'">
- <h1>
- <span :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
- <i class="fa icon-retweet 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>
- <div class="notification-content" v-html="notification.status.statusnet_html"></div>
- </div>
- <div v-if="notification.type === 'mention'">
- <h1>
- <span :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
- <i class="fa icon-reply 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>
- <status :compact="true" :statusoid="notification.status"></status>
- </div>
- <div v-if="notification.type === 'follow'">
- <h1>
- <span :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
- <i class="fa icon-user-plus lit"></i>
- </h1>
- <div>
- <router-link :to="{ name: 'user-profile', params: { id: notification.action.user.id } }">@{{ notification.action.user.screen_name }}</router-link> {{$t('notifications.followed_you')}}
- </div>
- </div>
- </div>
+ <div class="panel-body">
+ <div v-for="notification in visibleNotifications" :key="notification.action.id" class="notification" :class='{"unseen": !notification.seen}'>
+ <notification :notification="notification"></notification>
</div>
</div>
</div>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 999aa732..6c95873c 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -28,6 +28,9 @@ const PostStatusForm = {
components: {
MediaUpload
},
+ mounted () {
+ this.resize(this.$refs.textarea)
+ },
data () {
let statusText = ''
@@ -53,7 +56,8 @@ const PostStatusForm = {
candidates () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === '@') {
- const matchedUsers = filter(this.users, (user) => (String(user.name + user.screen_name)).match(this.textAtCaret.slice(1)))
+ const matchedUsers = filter(this.users, (user) => (String(user.name + user.screen_name)).toUpperCase()
+ .match(this.textAtCaret.slice(1).toUpperCase()))
if (matchedUsers.length <= 0) {
return false
}
@@ -234,10 +238,14 @@ const PostStatusForm = {
e.dataTransfer.dropEffect = 'copy'
},
resize (e) {
- e.target.style.height = 'auto'
- e.target.style.height = `${e.target.scrollHeight - 10}px`
- if (e.target.value === '') {
- e.target.style.height = '16px'
+ const target = e.target || e
+ target.style.height = 'auto'
+ const heightPx = target.scrollHeight - 10
+ if (heightPx > 54) {
+ target.style.height = `${target.scrollHeight - 10}px`
+ }
+ if (target.value === '') {
+ target.style.height = '16px'
}
},
clearError () {
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 4871bcae..88627e3a 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -1,21 +1,36 @@
<template>
- <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.down="cycleForward" @keydown.up="cycleBackward" @keydown.shift.tab="cycleBackward" @keydown.tab="cycleForward" @keydown.enter="replaceCandidate" @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">
+<div class="post-status-form">
+ <form @submit.prevent="postStatus(newStatus)">
+ <div class="form-group" >
+ <textarea
+ ref="textarea"
+ @click="setCaret"
+ @keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control"
+ @keydown.down="cycleForward"
+ @keydown.up="cycleBackward"
+ @keydown.shift.tab="cycleBackward"
+ @keydown.tab="cycleForward"
+ @keydown.enter="replaceCandidate"
+ @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">
<div v-for="candidate in candidates" @click="replace(candidate.utf || (candidate.screen_name + ' '))">
- <div v-if="candidate.highlighted" class="autocomplete base02">
+ <div v-if="candidate.highlighted" class="autocomplete">
<span v-if="candidate.img"><img :src="candidate.img"></span>
<span v-else>{{candidate.utf}}</span>
- <span>{{candidate.screen_name}}<small class="base02">{{candidate.name}}</small></span>
+ <span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
</div>
- <div v-else class="autocomplete base04">
+ <div v-else class="autocomplete">
<span v-if="candidate.img"><img :src="candidate.img"></img></span>
<span v-else>{{candidate.utf}}</span>
- <span>{{candidate.screen_name}}<small class="base02">{{candidate.name}}</small></span>
+ <span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
</div>
</div>
</div>
@@ -24,18 +39,18 @@
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
<p v-if="isOverLengthLimit" class="error">{{ charactersLeft }}</p>
- <p v-else-if="hasStatusLengthLimit" class="base04">{{ charactersLeft }}</p>
+ <p class="faint" v-else-if="hasStatusLengthLimit">{{ charactersLeft }}</p>
- <button v-if="posting" disabled class="btn btn-default base05 base02-background">{{$t('post_status.posting')}}</button>
- <button v-else-if="isOverLengthLimit" disabled class="btn btn-default base05 base02-background">{{$t('general.submit')}}</button>
- <button v-else :disabled="submitDisabled" type="submit" class="btn btn-default base05 base02-background">{{$t('general.submit')}}</button>
+ <button v-if="posting" disabled class="btn btn-default">{{$t('post_status.posting')}}</button>
+ <button v-else-if="isOverLengthLimit" disabled class="btn btn-default">{{$t('general.submit')}}</button>
+ <button v-else :disabled="submitDisabled" type="submit" class="btn btn-default">{{$t('general.submit')}}</button>
</div>
- <div class='error' v-if="error">
+ <div class='alert error' v-if="error">
Error: {{ error }}
<i class="icon-cancel" @click="clearError"></i>
</div>
<div class="attachments">
- <div class="media-upload-container attachment base03-border" v-for="file in newStatus.files">
+ <div class="media-upload-container attachment" 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>
@@ -50,147 +65,157 @@
<script src="./post_status_form.js"></script>
<style lang="scss">
-
- .tribute-container {
- ul {
- padding: 0px;
- li {
- display: flex;
- align-items: center;
- }
- }
- img {
- padding: 3px;
- width: 16px;
- height: 16px;
- border-radius: 50%;
- }
- }
-
- .post-status-form, .login {
- .form-bottom {
- display: flex;
- padding: 0.5em;
- height: 32px;
-
- button {
- width: 10em;
- }
-
- p {
- margin: 0.35em;
- padding: 0.35em;
- display: flex;
- }
- }
- .error {
- border-radius: 5px;
- text-align: center;
- background-color: rgba(255, 48, 16, 0.65);
- padding: 0.25em;
- margin: 0.35em;
- display: flex;
- }
-
- .attachments {
- padding: 0 0.5em;
-
- .attachment {
- position: relative;
- margin: 0.5em 0.8em 0.2em 0;
- }
-
- i {
- position: absolute;
- margin: 10px;
- padding: 5px;
- background: rgba(230,230,230,0.6);
- border-radius: 5px;
- font-weight: bold;
- }
- }
-
-
- .btn {
- cursor: pointer;
- }
-
- .btn[disabled] {
- cursor: not-allowed;
- }
-
- .icon-cancel {
- cursor: pointer;
- }
- form {
- display: flex;
- flex-direction: column;
- padding: 0.6em;
- }
-
- .form-group {
- display: flex;
- flex-direction: column;
- padding: 0.3em 0.5em 0.6em;
- line-height:24px;
- }
-
- form textarea {
- border: solid;
- border-width: 1px;
- border-color: inherit;
- border-radius: 5px;
- line-height:16px;
- padding: 5px;
- resize: none;
- overflow: hidden;
- }
-
- form textarea:focus {
- min-height: 48px;
- }
-
- .btn {
- cursor: pointer;
- }
-
- .btn[disabled] {
- cursor: not-allowed;
- }
-
- .icon-cancel {
- cursor: pointer;
- z-index: 4;
- }
-
- .autocomplete-panel {
- margin: 0 0.5em 0 0.5em;
- border-radius: 5px;
- position: absolute;
- z-index: 1;
- box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
- min-width: 75%;
- }
-
- .autocomplete {
- cursor: pointer;
- padding: 0.2em 0.4em 0.2em 0.4em;
- border-bottom: 1px solid rgba(0, 0, 0, 0.4);
- display: flex;
- img {
- width: 24px;
- height: 24px;
- border-radius: 2px;
- object-fit: contain;
- }
- span {
- line-height: 24px;
- margin: 0 0.1em 0 0.2em;
- }
- small {
- font-style: italic;
- }
- }
- }
-
+@import '../../_variables.scss';
+
+.tribute-container {
+ ul {
+ padding: 0px;
+ li {
+ display: flex;
+ align-items: center;
+ }
+ }
+ img {
+ padding: 3px;
+ width: 16px;
+ height: 16px;
+ border-radius: $fallback--avatarAltRadius;
+ border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+ }
+}
+
+.post-status-form, .login {
+ .form-bottom {
+ display: flex;
+ padding: 0.5em;
+ height: 32px;
+
+ button {
+ width: 10em;
+ }
+
+ p {
+ margin: 0.35em;
+ padding: 0.35em;
+ display: flex;
+ }
+ }
+
+ .error {
+ text-align: center;
+ }
+
+ .attachments {
+ padding: 0 0.5em;
+
+ .attachment {
+ position: relative;
+ border: 1px solid $fallback--border;
+ border: 1px solid var(--border, $fallback--border);
+ margin: 0.5em 0.8em 0.2em 0;
+ }
+
+ i {
+ position: absolute;
+ margin: 10px;
+ padding: 5px;
+ background: rgba(230,230,230,0.6);
+ border-radius: $fallback--attachmentRadius;
+ border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
+ font-weight: bold;
+ }
+ }
+
+
+ .btn {
+ cursor: pointer;
+ }
+
+ .btn[disabled] {
+ cursor: not-allowed;
+ }
+
+ .icon-cancel {
+ cursor: pointer;
+ }
+
+ form {
+ display: flex;
+ flex-direction: column;
+ padding: 0.6em;
+ }
+
+ .form-group {
+ display: flex;
+ flex-direction: column;
+ padding: 0.3em 0.5em 0.6em;
+ line-height:24px;
+ }
+
+ form textarea {
+ line-height:16px;
+ resize: none;
+ overflow: hidden;
+ transition: min-height 200ms 100ms;
+ min-height: 1px;
+ box-sizing: content-box;
+ }
+
+ form textarea:focus {
+ min-height: 48px;
+ }
+
+ .btn {
+ cursor: pointer;
+ }
+
+ .btn[disabled] {
+ cursor: not-allowed;
+ }
+
+ .icon-cancel {
+ cursor: pointer;
+ z-index: 4;
+ }
+
+ .autocomplete-panel {
+ margin: 0 0.5em 0 0.5em;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ position: absolute;
+ z-index: 1;
+ box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
+ min-width: 75%;
+ background: $fallback--btn;
+ background: var(--btn, $fallback--btn);
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+ }
+
+ .autocomplete {
+ cursor: pointer;
+ padding: 0.2em 0.4em 0.2em 0.4em;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.4);
+ display: flex;
+
+ img {
+ width: 24px;
+ height: 24px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ object-fit: contain;
+ }
+
+ span {
+ line-height: 24px;
+ margin: 0 0.1em 0 0.2em;
+ }
+
+ small {
+ margin-left: .5em;
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ }
+ }
+}
</style>
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index adc751a3..00f665af 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -1,6 +1,6 @@
<template>
- <div class="settings panel panel-default base00-background">
- <div class="panel-heading base02-background base04">
+ <div class="settings panel panel-default">
+ <div class="panel-heading">
{{$t('registration.registration')}}
</div>
<div class="panel-body">
@@ -39,14 +39,14 @@
</div>
-->
<div class='form-group'>
- <button :disabled="registering" type='submit' class='btn btn-default base05 base02-background'>{{$t('general.submit')}}</button>
+ <button :disabled="registering" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button>
</div>
</div>
<div class='terms-of-service' v-html="termsofservice">
</div>
</div>
<div v-if="error" class='form-group'>
- <div class='error base05'>{{error}}</div>
+ <div class='alert error'>{{error}}</div>
</div>
</form>
</div>
@@ -55,6 +55,7 @@
<script src="./registration.js"></script>
<style lang="scss">
+@import '../../_variables.scss';
.registration-form {
display: flex;
@@ -87,23 +88,10 @@
}
form textarea {
- border: solid;
- border-width: 1px;
- border-color: silver;
- border-radius: 5px;
line-height:16px;
- padding: 5px;
resize: vertical;
}
- input {
- border-width: 1px;
- border-style: solid;
- border-color: silver;
- border-radius: 5px;
- padding: 0.1em 0.2em 0.2em 0.2em;
- }
-
.captcha {
max-width: 350px;
margin-bottom: 0.4em;
@@ -117,12 +105,7 @@
}
.error {
- border-radius: 5px;
text-align: center;
- margin: 0.5em 0.6em 0;
- background-color: rgba(255, 48, 16, 0.65);
- min-height: 28px;
- line-height: 28px;
}
}
diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue
index 7a7ea763..1bee3d08 100644
--- a/src/components/retweet_button/retweet_button.vue
+++ b/src/components/retweet_button/retweet_button.vue
@@ -1,26 +1,28 @@
<template>
<div v-if="loggedIn">
- <i :class='classes' class='icon-retweet rt-active base09' v-on:click.prevent='retweet()'></i>
+ <i :class='classes' class='icon-retweet rt-active' v-on:click.prevent='retweet()'></i>
<span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span>
</div>
<div v-else>
- <i :class='classes' class='icon-retweet base09'></i>
+ <i :class='classes' class='icon-retweet'></i>
<span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span>
</div>
</template>
<script src="./retweet_button.js" ></script>
-<style lang='scss'>
- @import '../../_variables.scss';
- .rt-active {
- cursor: pointer;
- animation-duration: 0.6s;
- &:hover {
- color: $green;
- }
- }
- .icon-retweet.retweeted {
- color: $green;
+<style lang="scss">
+@import '../../_variables.scss';
+.rt-active {
+ cursor: pointer;
+ animation-duration: 0.6s;
+ &:hover {
+ color: $fallback--cGreen;
+ color: var(--cGreen, $fallback--cGreen);
}
+}
+.icon-retweet.retweeted {
+ color: $fallback--cGreen;
+ color: var(--cGreen, $fallback--cGreen);
+}
</style>
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index b88937bb..a26111d6 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -10,7 +10,8 @@ const settings = {
muteWordsString: this.$store.state.config.muteWords.join('\n'),
autoLoadLocal: this.$store.state.config.autoLoad,
streamingLocal: this.$store.state.config.streaming,
- hoverPreviewLocal: this.$store.state.config.hoverPreview
+ hoverPreviewLocal: this.$store.state.config.hoverPreview,
+ stopGifs: this.$store.state.config.stopGifs
}
},
components: {
@@ -43,6 +44,9 @@ const settings = {
muteWordsString (value) {
value = filter(value.split('\n'), (word) => trim(word).length > 0)
this.$store.dispatch('setOption', { name: 'muteWords', value })
+ },
+ stopGifs (value) {
+ this.$store.dispatch('setOption', { name: 'stopGifs', value })
}
}
}
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 8fdd09de..b4514ba1 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -1,6 +1,6 @@
<template>
- <div class="settings panel panel-default base00-background">
- <div class="panel-heading base02-background base04">
+ <div class="settings panel panel-default">
+ <div class="panel-heading">
{{$t('settings.settings')}}
</div>
<div class="panel-body">
@@ -29,8 +29,8 @@
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
</li>
<li>
- <input type="checkbox" id="autoLoad" v-model="autoLoadLocal">
- <label for="autoLoad">{{$t('settings.autoload')}}</label>
+ <input type="checkbox" id="autoload" v-model="autoLoadLocal">
+ <label for="autoload">{{$t('settings.autoload')}}</label>
</li>
<li>
<input type="checkbox" id="streaming" v-model="streamingLocal">
@@ -40,6 +40,10 @@
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
</li>
+ <li>
+ <input type="checkbox" id="stopGifs" v-model="stopGifs">
+ <label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
+ </li>
</ul>
</div>
</div>
@@ -50,32 +54,40 @@
</script>
<style lang="scss">
- .setting-item {
- margin: 1em 1em 1.4em;
- textarea {
- width: 100%;
- height: 100px;
- }
+@import '../../_variables.scss';
+
+.setting-item {
+ margin: 1em 1em 1.4em;
+
+ textarea {
+ width: 100%;
+ height: 100px;
+ }
- .old-avatar {
- width: 128px;
- border-radius: 5px;
- }
+ .old-avatar {
+ width: 128px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ }
- .new-avatar {
- object-fit: cover;
- width: 128px;
- height: 128px;
- border-radius: 5px;
- }
+ .new-avatar {
+ object-fit: cover;
+ width: 128px;
+ height: 128px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ }
- .btn {
- margin-top: 1em;
- min-height: 28px;
- width: 10em;
- }
- }
- .setting-list {
- list-style-type: none;
- }
+ .btn {
+ margin-top: 1em;
+ min-height: 28px;
+ width: 10em;
+ }
+}
+.setting-list {
+ list-style-type: none;
+ li {
+ margin-bottom: 0.5em;
+ }
+}
</style>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 12f3bb25..73f4a7aa 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -4,9 +4,11 @@ import RetweetButton from '../retweet_button/retweet_button.vue'
import DeleteButton from '../delete_button/delete_button.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue'
import UserCardContent from '../user_card_content/user_card_content.vue'
+import StillImage from '../still-image/still-image.vue'
import { filter, find } from 'lodash'
const Status = {
+ name: 'Status',
props: [
'statusoid',
'expandable',
@@ -14,7 +16,10 @@ const Status = {
'focused',
'highlight',
'compact',
- 'replies'
+ 'replies',
+ 'noReplyLinks',
+ 'noHeading',
+ 'inlineExpanded'
],
data: () => ({
replying: false,
@@ -22,7 +27,8 @@ const Status = {
unmuted: false,
userExpanded: false,
preview: null,
- showPreview: false
+ showPreview: false,
+ showingTall: false
}),
computed: {
muteWords () {
@@ -54,11 +60,6 @@ const Status = {
},
muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) },
isReply () { return !!this.status.in_reply_to_status_id },
- borderColor () {
- return {
- borderBottomColor: this.$store.state.config.colors['base02']
- }
- },
isFocused () {
// retweet or root of an expanded conversation
if (this.focused) {
@@ -68,6 +69,29 @@ const Status = {
}
// use conversation highlight only when in conversation
return this.status.id === this.highlight
+ },
+ // This is a bit hacky, but we want to approximate post height before rendering
+ // so we count newlines (masto uses <p> for paragraphs, GS uses <br> between them)
+ // as well as approximate line count by counting characters and approximating ~80
+ // per line.
+ //
+ // Using max-height + overflow: auto for status components resulted in false positives
+ // very often with japanese characters, and it was very annoying.
+ hideTallStatus () {
+ if (this.showingTall) {
+ return false
+ }
+ const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
+ return lengthScore > 20
+ },
+ attachmentSize () {
+ if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
+ (this.$store.state.config.hideAttachmentsInConv && this.inConversation)) {
+ return 'hide'
+ } else if (this.compact) {
+ return 'small'
+ }
+ return 'normal'
}
},
components: {
@@ -76,7 +100,8 @@ const Status = {
RetweetButton,
DeleteButton,
PostStatusForm,
- UserCardContent
+ UserCardContent,
+ StillImage
},
methods: {
linkClicked ({target}) {
@@ -105,6 +130,9 @@ const Status = {
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
},
+ toggleShowTall () {
+ this.showingTall = !this.showingTall
+ },
replyEnter (id, event) {
this.showPreview = true
const targetId = Number(id)
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 28272b0b..f1163fd9 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -1,123 +1,99 @@
<template>
- <div class="status-el base00-background" v-if="compact">
- <div @click.prevent="linkClicked" class="status-content" v-html="status.statusnet_html"></div>
- <div v-if="loggedIn">
- <div class='status-actions'>
- <div>
- <a href="#" v-on:click.prevent="toggleReplying">
- <i class="base09 icon-reply" :class="{'icon-reply-active': replying}"></i>
- </a>
- </div>
- <retweet-button :loggedIn="loggedIn" :status=status></retweet-button>
- <favorite-button :loggedIn="loggedIn" :status=status></favorite-button>
- </div>
- </div>
- <post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" v-on:posted="toggleReplying" v-if="replying"/>
- </div>
- <div class="status-el base00-background base03-border status-fadein" v-else-if="!status.deleted" v-bind:class="[{ 'base01-background': isFocused }, { 'status-conversation': inConversation }]" >
- <template v-if="muted">
+ <div class="status-el" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
+ <template v-if="muted && !noReplyLinks">
<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="base09 icon-eye-off"></i></a>
+ <a href="#" class="unmute" @click.prevent="toggleMute"><i class="icon-eye-off"></i></a>
</div>
</template>
- <template v-if="!muted">
- <div v-if="retweet" class="media container retweet-info">
- <div class="media-left">
+ <template v-else>
+ <div v-if="retweet && !noHeading" class="media container retweet-info">
+ <StillImage v-if="retweet" class='avatar' :src="statusoid.user.profile_image_url_original"/>
+ <div class="media-body faint">
+ <a :href="statusoid.user.statusnet_profile_url" style="font-weight: bold;" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
<i class='fa icon-retweet retweeted'></i>
- </div>
- <div class="media-body">
- Repeated by <a :href="statusoid.user.statusnet_profile_url" style="font-weight: bold;" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
+ {{$t('timeline.repeated')}}
</div>
</div>
- <div class="media status container">
- <div class="media-left">
- <a :href="status.user.statusnet_profile_url">
- <img @click.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original">
- <img v-if="retweet" class='avatar-retweeter' :src="statusoid.user.profile_image_url_original"></img>
+
+ <div class="media status">
+ <div v-if="!noHeading" class="media-left">
+ <a :href="status.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
+ <StillImage class='avatar' :class="{'avatar-compact': compact}" :src="status.user.profile_image_url_original"/>
</a>
</div>
- <div class="media-body">
- <div class="base03-border usercard" v-if="userExpanded">
+ <div class="status-body">
+ <div class="usercard media-body" v-if="userExpanded">
<user-card-content :user="status.user" :switcher="false"></user-card-content>
</div>
- <div class="user-content">
- <div class="media-heading">
+ <div v-if="!noHeading" class="media-body container media-heading">
+ <div class="media-heading-left">
<div class="name-and-links">
<h4 class="user-name">{{status.user.name}}</h4>
- <div class="links">
- <h4>
- <small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
- <small v-if="status.in_reply_to_screen_name"> &gt;
+ <span class="links">
+ <router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link>
+ <span v-if="status.in_reply_to_screen_name" class="faint reply-info">
+ <i class="icon-right-open"></i>
<router-link :to="{ name: 'user-profile', params: { id: status.in_reply_to_user_id } }">
{{status.in_reply_to_screen_name}}
</router-link>
- </small>
- <template v-if="isReply">
- <small>
- <a href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)"><i class="icon-reply" @mouseenter="replyEnter(status.in_reply_to_status_id, $event)" @mouseout="replyLeave()"></i></a>
- </small>
- </template>
- -
- <small>
- <router-link :to="{ name: 'conversation', params: { id: status.id } }">
- <timeago :since="status.created_at" :auto-update="60"></timeago>
- </router-link>
- </small>
- </h4>
- </div>
- <h4 class="replies" v-if="inConversation">
- <small v-if="replies.length">Replies:</small>
- <small v-for="reply in replies">
- <a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}&nbsp;</a>
- </small>
- </h4>
- </div>
- <div class="heading-icons">
- <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="base09 icon-plus-squared"></i></a>
- </template>
+ </span>
+ <a v-if="isReply && !noReplyLinks" href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)">
+ <i class="icon-reply" @mouseenter="replyEnter(status.in_reply_to_status_id, $event)" @mouseout="replyLeave()"></i>
+ </a>
+ </span>
</div>
+ <h4 class="replies" v-if="inConversation && !noReplyLinks">
+ <small v-if="replies.length">Replies:</small>
+ <small class="reply-link" v-for="reply in replies">
+ <a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}&nbsp;</a>
+ </small>
+ </h4>
</div>
-
- <div class="status-preview base00-background base03-border" v-if="showPreview && preview">
- <img class="avatar" :src="preview.user.profile_image_url_original">
- <div class="text">
- <h4>
- {{ preview.user.name }}
- <small><a>{{ preview.user.screen_name}}</a></small>
- </h4>
- <div @click.prevent="linkClicked" class="status-content" v-html="preview.statusnet_html"></div>
- </div>
+ <div class="media-heading-right">
+ <router-link class="timeago" :to="{ name: 'conversation', params: { id: status.id } }">
+ <timeago :since="status.created_at" :auto-update="60"></timeago>
+ </router-link>
+ <a :href="status.external_url" target="_blank" v-if="!status.is_local" class="source_url"><i class="icon-link-ext"></i></a>
+ <template v-if="expandable">
+ <a href="#" @click.prevent="toggleExpanded"><i class="icon-plus-squared"></i></a>
+ </template>
+ <a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="icon-eye-off"></i></a>
</div>
- <div class="status-preview status-preview-loading base00-background base03-border" v-else-if="showPreview">
- <i class="base09 icon-spin4 animate-spin"></i>
+ </div>
+
+ <div v-if="showPreview" class="status-preview-container">
+ <status class="status-preview" v-if="preview" :noReplyLinks="true" :statusoid="preview" :compact=true></status>
+ <div class="status-preview status-preview-loading" v-else>
+ <i class="icon-spin4 animate-spin"></i>
</div>
+ </div>
- <div @click.prevent="linkClicked" class="status-content" v-html="status.statusnet_html"></div>
+ <div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper">
+ <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowTall">Show more</a>
+ <div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html"></div>
+ <a v-if="showingTall" href="#" class="tall-status-unhider" @click.prevent="toggleShowTall">Show less</a>
+ </div>
- <div v-if='status.attachments' class='attachments'>
- <attachment v-if="!hideAttachments" :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
- </attachment>
- </div>
+ <div v-if='status.attachments' class='attachments media-body'>
+ <attachment :size="attachmentSize" :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
+ </attachment>
</div>
- <div class='status-actions'>
+ <div v-if="!noHeading && !noReplyLinks" class='status-actions media-body'>
<div v-if="loggedIn">
<a href="#" v-on:click.prevent="toggleReplying">
- <i class="base09 icon-reply" :class="{'icon-reply-active': replying}"></i>
+ <i class="icon-reply" :class="{'icon-reply-active': replying}"></i>
</a>
</div>
- <retweet-button :loggedIn="loggedIn" :status=status></retweet-button>
- <favorite-button :loggedIn="loggedIn" :status=status></favorite-button>
- <delete-button :status=status></delete-button>
+ <retweet-button :loggedIn='loggedIn' :status='status'></retweet-button>
+ <favorite-button :loggedIn='loggedIn' :status='status'></favorite-button>
+ <delete-button :status='status'></delete-button>
</div>
</div>
</div>
- <div class="status base00-background container" v-if="replying">
+ <div class="container" v-if="replying">
<div class="reply-left"/>
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" v-on:posted="toggleReplying"/>
</div>
@@ -126,300 +102,387 @@
</template>
<script src="./status.js" ></script>
-
<style lang="scss">
- @import '../../_variables.scss';
+@import '../../_variables.scss';
+
+.status-body {
+ flex: 1;
+ min-width: 0;
+}
+
+.status-preview.status-el {
+ border-style: solid;
+ border-width: 1px;
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+}
+
+.status-preview-container {
+ position: relative;
+ max-width: 100%;
+}
+
+.status-preview {
+ position: absolute;
+ max-width: 95%;
+ display: flex;
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
+ margin-top: 0.25em;
+ margin-left: 0.5em;
+ z-index: 50;
+ .status {
+ flex: 1;
+ border: 0;
+ min-width: 15em;
+ }
+}
+
+.status-preview-loading {
+ display: block;
+ min-width: 15em;
+ padding: 1em;
+ text-align: center;
+ border-width: 1px;
+ border-style: solid;
+ i {
+ font-size: 2em;
+ }
+}
+
+.status-el {
+ hyphens: auto;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ word-break: break-word;
+ border-left-width: 0px;
+ line-height: 18px;
+ min-width: 0;
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+
+ border-left: 4px $fallback--cRed;
+ border-left: 4px var(--cRed, $fallback--cRed);
+
+ &_focused {
+ background-color: $fallback--lightBg;
+ background-color: var(--lightBg, $fallback--lightBg);
+ }
- status-text-container {
- display: block;
+ .timeline & {
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
}
- .status-preview {
- position: absolute;
- max-width: 34em;
- padding: 0.5em;
+ .media-body {
+ flex: 1;
+ padding: 0;
+ margin: 0 0 0.25em 0.8em;
+ }
+
+ .media-heading {
+ flex-wrap: nowrap;
+ }
+
+ .media-heading-left {
+ padding: 0;
+ vertical-align: bottom;
+ flex-basis: 100%;
+
+ small {
+ font-weight: lighter;
+ }
+ h4 {
+ white-space: nowrap;
+ font-size: 14px;
+ margin-right: 0.25em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .name-and-links {
+ padding: 0;
+ flex: 1 0;
+ display: flex;
+ flex-wrap: wrap;
+ align-content: center;
+ }
+ .links {
+ display: flex;
+ padding-top: 1px;
+ margin-left: 0.2em;
+ font-size: 12px;
+ color: $fallback--link;
+ color: var(--link, $fallback--link);
+ max-width: 100%;
+ a {
+ max-width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ }
+ .reply-info {
+ display: flex;
+ }
+ .replies {
+ line-height: 16px;
+ }
+ .reply-link {
+ margin-right: 0.2em;
+ }
+ }
+
+ .media-heading-right {
+ flex-shrink: 0;
display: flex;
- border-color: inherit;
- border-style: solid;
- border-width: 1px;
- border-radius: 4px;
- box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
- margin-top: 0.5em;
- margin-left: 1em;
+ flex-wrap: nowrap;
+ max-height: 1.5em;
+ margin-left: 0.25em;
+ .timeago {
+ margin-right: 0.2em;
+ font-size: 12px;
+ padding-top: 1px;
+ }
+ i {
+ margin-left: 0.2em;
+ }
+ }
+ a {
+ display: inline-block;
+ word-break: break-all;
+ }
+
+ .tall-status {
+ position: relative;
+ height: 220px;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ }
+
+ .tall-status-hider {
+ position: absolute;
+ height: 70px;
+ margin-top: 150px;
+ width: 100%;
+ text-align: center;
+ line-height: 110px;
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%);
+ &_focused {
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--lightBg 80%);
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--lightBg, $fallback--lightBg) 80%);
+ }
+ }
+
+ .tall-status-unhider {
+ width: 100%;
+ text-align: center;
+ }
+
+ .status-content {
+ margin-right: 0.5em;
+ img, video {
+ max-width: 100%;
+ max-height: 400px;
+ vertical-align: middle;
+ object-fit: contain;
+ }
+
+ blockquote {
+ margin: 0.2em 0 0.2em 2em;
+ font-style: italic;
+ }
+
+ p {
+ margin: 0;
+ margin-top: 0.2em;
+ margin-bottom: 0.5em;
+ }
+ }
+
+ .retweet-info {
+ padding: 0.4em 0.6em 0 0.6em;
+ margin: 0 0 -0.5em 0;
.avatar {
- flex-shrink: 0;
- width: 32px;
- height: 32px;
- border-radius: 50%;
+ border-radius: $fallback--avatarAltRadius;
+ border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+ margin-left: 28px;
+ width: 20px;
+ height: 20px;
}
- .text {
- h4 {
- margin-bottom: 0.4em;
- small {
- font-weight: lighter;
- }
+
+ .media-body {
+ font-size: 1em;
+ line-height: 22px;
+
+ display: flex;
+ align-content: center;
+ flex-wrap: wrap;
+ i {
+ padding: 0 0.2em;
+ }
+ a {
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
- padding: 0 0.5em 0.5em 0.5em;
}
}
+}
- .status-preview-loading {
- display: block;
- font-size: 2em;
- min-width: 8em;
- text-align: center;
+.status-fadein {
+ animation-duration: 0.4s;
+ animation-name: fadein;
+}
+
+@keyframes fadein {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+.greentext {
+ color: green;
+}
+
+.status-conversation {
+ border-left-style: solid;
+}
+
+.status-actions {
+ width: 100%;
+ display: flex;
+
+ div, favorite-button {
+ padding-top: 0.25em;
+ max-width: 6em;
+ flex: 1;
+ }
+}
+
+.icon-reply:hover {
+ color: $fallback--cBlue;
+ color: var(--cBlue, $fallback--cBlue);
+}
+
+.icon-reply.icon-reply-active {
+ color: $fallback--cBlue;
+ color: var(--cBlue, $fallback--cBlue);
+}
+
+.status .avatar-compact {
+ width: 32px;
+ height: 32px;
+ border-radius: $fallback--avatarAltRadius;
+ border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+}
+
+.avatar {
+ width: 48px;
+ height: 48px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ overflow: hidden;
+ position: relative;
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+
+ &.animated::before {
+ display: none;
+ }
+
+ &.retweeted {
+ }
+}
+
+.status:hover .animated.avatar {
+ canvas {
+ display: none;
+ }
+ img {
+ visibility: visible;
+ }
+}
+
+.status {
+ display: flex;
+ padding: 0.6em;
+}
+
+.status-conversation:last-child {
+ border-bottom: none;
+}
+
+.muted {
+ padding: 0.25em 0.5em;
+ button {
+ margin-left: auto;
}
- .status-el {
- hyphens: auto;
- overflow-wrap: break-word;
- word-wrap: break-word;
- word-break: break-word;
- border-left-width: 0px;
- line-height: 18px;
-
- .timeline & {
- border-bottom-width: 1px;
- border-bottom-style: solid;
- }
-
- .notify {
- .avatar {
- border-width: 3px;
- border-style: solid;
- }
- }
-
- .media-body {
- flex: 1;
- padding-left: 0.5em;
- }
-
-
- .user-content {
-
- min-height: 52px;
- padding-top: 1px;
- }
-
- .media-heading {
- display: flex;
- min-height: 1.4em;
- margin-bottom: 0.3em;
-
- small {
- font-weight: lighter;
- }
- h4 {
- margin-right: 0.4em;
- }
- .name-and-links {
- flex: 1 0;
- display: flex;
- flex-wrap: wrap;
- }
- .replies {
- flex-basis: 100%;
- }
- }
-
- .source_url {
-
- }
-
- .expand {
- margin-right: -0.3em;
- }
-
- a {
- display: inline-block;
- word-break: break-all;
- }
-
- .status-content {
- margin: 3px 15px 4px 0;
- max-height: 400px;
- overflow-y: auto;
- overflow-x: hidden;
-
- img, video {
- max-width: 100%;
- max-height: 400px;
- vertical-align: middle;
- object-fit: contain;
- }
-
- blockquote {
- margin: 0.2em 0 0.2em 2em;
- font-style: italic;
- }
- }
-
- p {
- margin: 0;
- margin-top: 0.2em;
- margin-bottom: 0.5em;
- }
-
- .media-left {
- margin: 0.2em 0.3em 0 0;
- img {
- float: right;
- border-radius: 5px;
- }
- }
-
- .retweet-info {
- padding: 0.7em 0 0 0.6em;
-
- .media-left {
- display: flex;
-
- i {
- align-self: center;
- text-align: right;
- flex: 1;
- padding-right: 0.3em;
- }
- }
- }
- }
-
- .status-fadein {
- animation-duration: 0.5s;
- animation-name: fadein;
- }
-
- @keyframes fadein {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
- }
-
- .greentext {
- color: green;
- }
-
- .status-conversation {
- border-left-style: solid;
- }
-
- .status-actions {
- padding-top: 0.15em;
- width: 100%;
- display: flex;
-
- div, favorite-button {
- max-width: 6em;
- flex: 1;
- }
- }
-
- .icon-reply:hover {
- color: $blue;
- }
-
- .icon-reply.icon-reply-active {
- color: $blue;
- }
-
- .status .avatar {
- width: 48px;
- height: 48px;
-
- &.retweeted {
- width: 40px;
- height: 40px;
- margin-right: 8px;
- margin-bottom: 8px;
- }
- }
-
- .status img.avatar-retweeter {
- width: 24px;
- height: 24px;
- position: absolute;
- margin-left: 24px;
- margin-top: 24px;
- }
-
- .status.compact .avatar {
- width: 32px;
- }
-
- .status {
- padding: 0.4em 0.7em 0.45em 0.7em;
- border-left: 4px rgba(255, 48, 16, 0.65);
- border-left-style: inherit;
- }
-
- .status-conversation:last-child {
- border-bottom: none;
- }
-
- .timeline .panel.timeline {
- border-radius: 10px;
- overflow: hidden;
- }
-
- .muted {
- padding: 0.1em 0.4em 0.1em 0.8em;
- button {
- margin-left: auto;
- }
-
- .muteWords {
- margin-left: 10px;
- }
- }
-
- a.unmute {
- display: block;
- margin-left: auto;
- }
-
- .reply-left {
- flex: 0;
- min-width: 48px;
- }
-
- .reply-body {
- flex: 1;
- }
-
- @media all and (max-width: 960px) {
- .status-el {
- .name-and-links {
- margin-left: -0.25em;
- }
- }
- .status {
- max-width: 100%;
- }
-
- .status .avatar {
- width: 40px;
- height: 40px;
-
- &.retweeted {
- width: 34px;
- height: 34px;
- margin-right: 8px;
- margin-bottom: 8px;
- }
- }
-
- .status img.avatar-retweeter {
- width: 22px;
- height: 22px;
- position: absolute;
- margin-left: 18px;
- margin-top: 18px;
- }
- }
+ .muteWords {
+ margin-left: 10px;
+ }
+}
+
+a.unmute {
+ display: block;
+ margin-left: auto;
+}
+
+.reply-left {
+ flex: 0;
+ min-width: 48px;
+}
+
+.reply-body {
+ flex: 1;
+}
+
+.timeline > {
+ .status-el:last-child {
+ border-bottom-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;;
+ border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
+ }
+}
+
+@media all and (max-width: 960px) {
+ .status-el {
+ .retweet-info {
+ .avatar {
+ margin-left: 20px;
+ }
+ }
+ }
+ .status {
+ max-width: 100%;
+ }
+
+ .status .avatar {
+ width: 40px;
+ height: 40px;
+ }
+
+ .status .avatar-compact {
+ width: 32px;
+ height: 32px;
+ }
+}
</style>
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
new file mode 100644
index 00000000..0839aca5
--- /dev/null
+++ b/src/components/still-image/still-image.js
@@ -0,0 +1,26 @@
+const StillImage = {
+ props: [
+ 'src',
+ 'referrerpolicy',
+ 'mimetype'
+ ],
+ data () {
+ return {
+ stopGifs: this.$store.state.config.stopGifs
+ }
+ },
+ computed: {
+ animated () {
+ return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif'))
+ }
+ },
+ methods: {
+ onLoad () {
+ const canvas = this.$refs.canvas
+ if (!canvas) return
+ canvas.getContext('2d').drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
+ }
+ }
+}
+
+export default StillImage
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
new file mode 100644
index 00000000..a37c678d
--- /dev/null
+++ b/src/components/still-image/still-image.vue
@@ -0,0 +1,65 @@
+<template>
+ <div class='still-image' :class='{ animated: animated }' >
+ <canvas ref="canvas" v-if="animated"></canvas>
+ <img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad"/>
+ </div>
+</template>
+
+<script src="./still-image.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+.still-image {
+ position: relative;
+ line-height: 0;
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+
+ &:hover canvas {
+ display: none;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+
+ &.animated {
+ &:hover::before,
+ img {
+ visibility: hidden;
+ }
+
+ &:hover img {
+ visibility: visible
+ }
+
+ &::before {
+ content: 'gif';
+ position: absolute;
+ line-height: 10px;
+ font-size: 10px;
+ top: 5px;
+ left: 5px;
+ background: rgba(127,127,127,.5);
+ color: #FFF;
+ display: block;
+ padding: 2px 4px;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ z-index: 2;
+ }
+ }
+
+ canvas {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ }
+}
+</style>
diff --git a/src/components/style_switcher/style_switcher.js b/src/components/style_switcher/style_switcher.js
index a762f914..08bc7113 100644
--- a/src/components/style_switcher/style_switcher.js
+++ b/src/components/style_switcher/style_switcher.js
@@ -6,9 +6,19 @@ export default {
availableStyles: [],
selected: this.$store.state.config.theme,
bgColorLocal: '',
- fgColorLocal: '',
+ btnColorLocal: '',
textColorLocal: '',
- linkColorLocal: ''
+ linkColorLocal: '',
+ redColorLocal: '',
+ blueColorLocal: '',
+ greenColorLocal: '',
+ orangeColorLocal: '',
+ btnRadiusLocal: '',
+ panelRadiusLocal: '',
+ avatarRadiusLocal: '',
+ avatarAltRadiusLocal: '',
+ attachmentRadiusLocal: '',
+ tooltipRadiusLocal: ''
}
},
created () {
@@ -21,16 +31,29 @@ export default {
})
},
mounted () {
- 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'])
- this.linkColorLocal = rgbstr2hex(this.$store.state.config.colors['base08'])
+ this.bgColorLocal = rgbstr2hex(this.$store.state.config.colors.bg)
+ this.btnColorLocal = rgbstr2hex(this.$store.state.config.colors.btn)
+ this.textColorLocal = rgbstr2hex(this.$store.state.config.colors.fg)
+ this.linkColorLocal = rgbstr2hex(this.$store.state.config.colors.link)
+
+ this.redColorLocal = rgbstr2hex(this.$store.state.config.colors.cRed)
+ this.blueColorLocal = rgbstr2hex(this.$store.state.config.colors.cBlue)
+ this.greenColorLocal = rgbstr2hex(this.$store.state.config.colors.cGreen)
+ this.orangeColorLocal = rgbstr2hex(this.$store.state.config.colors.cOrange)
+
+ this.btnRadiusLocal = this.$store.state.config.radii.btnRadius || 4
+ this.panelRadiusLocal = this.$store.state.config.radii.panelRadius || 10
+ this.avatarRadiusLocal = this.$store.state.config.radii.avatarRadius || 5
+ this.avatarAltRadiusLocal = this.$store.state.config.radii.avatarAltRadius || 50
+ this.tooltipRadiusLocal = this.$store.state.config.radii.tooltipRadius || 2
+ this.attachmentRadiusLocal = this.$store.state.config.radii.attachmentRadius || 5
},
methods: {
setCustomTheme () {
- if (!this.bgColorLocal && !this.fgColorLocal && !this.linkColorLocal) {
+ if (!this.bgColorLocal && !this.btnColorLocal && !this.linkColorLocal) {
// reset to picked themes
}
+
const rgb = (hex) => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result ? {
@@ -40,17 +63,33 @@ export default {
} : null
}
const bgRgb = rgb(this.bgColorLocal)
- const fgRgb = rgb(this.fgColorLocal)
+ const btnRgb = rgb(this.btnColorLocal)
const textRgb = rgb(this.textColorLocal)
const linkRgb = rgb(this.linkColorLocal)
- if (bgRgb && fgRgb && linkRgb) {
+
+ const redRgb = rgb(this.redColorLocal)
+ const blueRgb = rgb(this.blueColorLocal)
+ const greenRgb = rgb(this.greenColorLocal)
+ const orangeRgb = rgb(this.orangeColorLocal)
+
+ if (bgRgb && btnRgb && linkRgb) {
this.$store.dispatch('setOption', {
name: 'customTheme',
value: {
- fg: fgRgb,
+ fg: btnRgb,
bg: bgRgb,
text: textRgb,
- link: linkRgb
+ link: linkRgb,
+ cRed: redRgb,
+ cBlue: blueRgb,
+ cGreen: greenRgb,
+ cOrange: orangeRgb,
+ btnRadius: this.btnRadiusLocal,
+ panelRadius: this.panelRadiusLocal,
+ avatarRadius: this.avatarRadiusLocal,
+ avatarAltRadius: this.avatarAltRadiusLocal,
+ tooltipRadius: this.tooltipRadiusLocal,
+ attachmentRadius: this.attachmentRadiusLocal
}})
}
}
@@ -58,9 +97,13 @@ export default {
watch: {
selected () {
this.bgColorLocal = this.selected[1]
- this.fgColorLocal = this.selected[2]
+ this.btnColorLocal = this.selected[2]
this.textColorLocal = this.selected[3]
this.linkColorLocal = this.selected[4]
+ this.redColorLocal = this.selected[5]
+ this.greenColorLocal = this.selected[6]
+ this.blueColorLocal = this.selected[7]
+ this.orangeColorLocal = this.selected[8]
}
}
}
diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue
index 31bf546d..9c39b245 100644
--- a/src/components/style_switcher/style_switcher.vue
+++ b/src/components/style_switcher/style_switcher.vue
@@ -1,99 +1,231 @@
<template>
<div>
- <p>{{$t('settings.presets')}}</p>
- <select v-model="selected" class="style-switcher">
- <option v-for="style in availableStyles" :value="style">{{style[0]}}</option>
- </select>
- <p>{{$t('settings.theme_help')}}</p>
+ <div>{{$t('settings.presets')}}
+ <label for="style-switcher" class='select'>
+ <select id="style-switcher" v-model="selected" class="style-switcher">
+ <option v-for="style in availableStyles" :value="style">{{style[0]}}</option>
+ </select>
+ <i class="icon-down-open"/>
+ </label>
+ </div>
<div class="color-container">
+ <p>{{$t('settings.theme_help')}}</p>
<div class="color-item">
- <label for="bgcolor" class="base04 theme-color-lb">{{$t('settings.background')}}</label>
+ <label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
<input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
<input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
</div>
<div class="color-item">
- <label for="fgcolor" class="base04 theme-color-lb">{{$t('settings.foreground')}}</label>
- <input id="fgcolor" class="theme-color-cl" type="color" v-model="fgColorLocal">
- <input id="fgcolor-t" class="theme-color-in" type="text" v-model="fgColorLocal">
+ <label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
+ <input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
+ <input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
</div>
<div class="color-item">
- <label for="textcolor" class="base04 theme-color-lb">{{$t('settings.text')}}</label>
+ <label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
<input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
<input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
</div>
<div class="color-item">
- <label for="linkcolor" class="base04 theme-color-lb">{{$t('settings.links')}}</label>
+ <label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
<input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
<input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
</div>
+ <div class="color-item">
+ <label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
+ <input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
+ <input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
+ </div>
+ <div class="color-item">
+ <label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
+ <input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
+ <input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
+ </div>
+ <div class="color-item">
+ <label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
+ <input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
+ <input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
+ </div>
+ <div class="color-item">
+ <label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
+ <input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
+ <input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
+ </div>
</div>
- <div>
- <div class="panel">
- <div class="panel-heading" :style="{ 'background-color': fgColorLocal, 'color': textColorLocal }">Preview</div>
+ <div class="radius-container">
+ <p>{{$t('settings.radii_help')}}</p>
+ <div class="radius-item">
+ <label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
+ <input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
+ <input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
+ </div>
+ <div class="radius-item">
+ <label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
+ <input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
+ <input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
+ </div>
+ <div class="radius-item">
+ <label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
+ <input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
+ <input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
+ </div>
+ <div class="radius-item">
+ <label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
+ <input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
+ <input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
+ </div>
+ <div class="radius-item">
+ <label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
+ <input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
+ <input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
+ </div>
+ <div class="radius-item">
+ <label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
+ <input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
+ <input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
+ </div>
+ </div>
+ <div :style="{
+ '--btnRadius': btnRadiusLocal + 'px',
+ '--panelRadius': panelRadiusLocal + 'px',
+ '--avatarRadius': avatarRadiusLocal + 'px',
+ '--avatarAltRadius': avatarAltRadiusLocal + 'px',
+ '--tooltipRadius': tooltipRadiusLocal + 'px',
+ '--attachmentRadius': attachmentRadiusLocal + 'px'
+ }">
+ <div class="panel dummy">
+ <div class="panel-heading" :style="{ 'background-color': btnColorLocal, 'color': textColorLocal }">Preview</div>
<div class="panel-body theme-preview-content" :style="{ 'background-color': bgColorLocal, 'color': textColorLocal }">
+ <div class="avatar" :style="{
+ 'border-radius': avatarRadiusLocal + 'px'
+ }">
+ ( ͡° ͜ʖ ͡°)
+ </div>
<h4>Content</h4>
<br>
A bunch of more content and
- <a :style="{ 'color': linkColorLocal }">a nice lil' link</a>
+ <a :style="{ color: linkColorLocal }">a nice lil' link</a>
+ <i :style="{ color: blueColorLocal }" class="icon-reply"/>
+ <i :style="{ color: greenColorLocal }" class="icon-retweet"/>
+ <i :style="{ color: redColorLocal }" class="icon-cancel"/>
+ <i :style="{ color: orangeColorLocal }" class="icon-star"/>
<br>
- <button class="btn" :style="{ 'background-color': fgColorLocal, 'color': textColorLocal }">Button</button>
+ <button class="btn" :style="{ 'background-color': btnColorLocal, 'color': textColorLocal }">Button</button>
</div>
</div>
</div>
- <button class="btn base02-background base04" @click="setCustomTheme">{{$t('general.apply')}}</button>
+ <button class="btn" @click="setCustomTheme">{{$t('general.apply')}}</button>
</div>
</template>
<script src="./style_switcher.js"></script>
<style lang="scss">
+@import '../../_variables.scss';
.style-switcher {
- margin-right: 1em;
+ margin-right: 1em;
}
+.radius-container,
.color-container {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
+ display: flex;
+
+ p {
+ margin-top: 2em;
+ margin-bottom: .5em;
+ }
+}
+.radius-container {
+ flex-direction: column;
}
+.color-container {
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
+.radius-item,
.color-item {
- min-width: 20em;
- display:flex;
- flex: 1 1 0;
- align-items: baseline;
- margin: 5px 6px 5px 0;
+ min-width: 20em;
+ display:flex;
+ flex: 1 1 0;
+ align-items: baseline;
+ margin: 5px 6px 5px 0;
+
+ label {
+ color: var(--faint, $fallback--faint);
+ }
}
+
+.radius-item {
+ flex-basis: auto;
+}
+
+.theme-radius-rn,
+.theme-color-cl {
+ border: 0;
+ box-shadow: none;
+ background: transparent;
+ color: var(--faint, $fallback--faint);
+ align-self: stretch;
+}
+
.theme-color-cl,
+.theme-radius-in,
.theme-color-in {
- margin-left: 4px;
- border-radius: 2px;
- border: 0;
+ margin-left: 4px;
}
.theme-color-in {
- padding: 5px;
- min-width: 4em;
- max-width: 7em;
- flex: 1;
+ min-width: 4em;
}
+
+.theme-radius-in {
+ min-width: 1em;
+}
+
+.theme-radius-in,
+.theme-color-in {
+ max-width: 7em;
+ flex: 1;
+}
+
+.theme-radius-lb,
.theme-color-lb {
- flex: 2;
- min-width: 7em;
- max-width: 10em;
+ flex: 2;
+ min-width: 7em;
+}
+
+.theme-radius-lb{
+ max-width: 50em;
+}
+
+.theme-color-lb {
+ max-width: 10em;
}
.theme-color-cl {
- padding: 1px;
- max-width: 8em;
- align-self: stretch;
- height: 100%;
- flex: 0;
- min-width: 2em;
- cursor: pointer;
- }
-
- .theme-preview-content {
- padding: 20px;
- }
+ padding: 1px;
+ max-width: 8em;
+ height: 100%;
+ flex: 0;
+ min-width: 2em;
+ cursor: pointer;
+}
+
+.theme-preview-content {
+ padding: 20px;
+}
+
+.dummy {
+ .avatar {
+ background: linear-gradient(135deg, #b8e1fc 0%,#a9d2f3 10%,#90bae4 25%,#90bcea 37%,#90bff0 50%,#6ba8e5 51%,#a2daf5 83%,#bdf3fd 100%);
+ color: black;
+ text-align: center;
+ height: 48px;
+ line-height: 48px;
+ width: 48px;
+ float: left;
+ margin-right: 1em;
+ }
+}
</style>
diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 660a8752..74ab85d3 100644
--- a/src/components/timeline/timeline.js
+++ b/src/components/timeline/timeline.js
@@ -105,7 +105,7 @@ const Timeline = {
.then((friends) => this.$store.dispatch('addFriends', { friends }))
},
scrollLoad (e) {
- let height = Math.max(document.body.offsetHeight, document.body.scrollHeight)
+ const height = Math.max(document.body.offsetHeight, document.body.scrollHeight)
if (this.timeline.loading === false &&
this.$store.state.config.autoLoad &&
this.$el.offsetHeight > 0 &&
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index d6ecfd2f..c4e0fbce 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -1,48 +1,50 @@
<template>
<div class="timeline panel panel-default" v-if="viewing == 'statuses'">
- <div class="panel-heading timeline-heading base02-background base04">
+ <div class="panel-heading timeline-heading">
<div class="title">
{{title}}
</div>
- <button @click.prevent="showNewStatuses" class="base05 base02-background loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError">
+ <button @click.prevent="showNewStatuses" class="loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError">
{{$t('timeline.show_new')}}{{newStatusCountStr}}
</button>
- <div @click.prevent class="base06 error loadmore-text" v-if="timelineError">
+ <div @click.prevent class="loadmore-error alert error" v-if="timelineError">
{{$t('timeline.error_fetching')}}
</div>
- <div @click.prevent class="base04 base02-background loadmore-text" v-if="!timeline.newStatusCount > 0 && !timelineError">
+ <div @click.prevent class="loadmore-text" v-if="!timeline.newStatusCount > 0 && !timelineError">
{{$t('timeline.up_to_date')}}
</div>
</div>
- <div class="panel-body base01-background">
+ <div class="panel-body">
<div class="timeline">
- <status-or-conversation v-for="status in timeline.visibleStatuses" :key="status.id" v-bind:statusoid="status"></status-or-conversation>
- <a href="#" v-on:click.prevent='fetchOlderStatuses()' v-if="!timeline.loading">
- <div class="base02-background base03-border new-status-notification text-center">{{$t('timeline.load_older')}}</div>
- </a>
- <div class="base02-background base03-border new-status-notification text-center" v-else>...</div>
+ <status-or-conversation v-for="status in timeline.visibleStatuses" :key="status.id" v-bind:statusoid="status" class="status-fadein"></status-or-conversation>
</div>
</div>
+ <div class="panel-footer">
+ <a href="#" v-on:click.prevent='fetchOlderStatuses()' v-if="!timeline.loading">
+ <div class="new-status-notification text-center panel-footer">{{$t('timeline.load_older')}}</div>
+ </a>
+ <div class="new-status-notification text-center panel-footer" v-else>...</div>
+ </div>
</div>
<div class="timeline panel panel-default" v-else-if="viewing == 'followers'">
- <div class="panel-heading timeline-heading base02-background base04">
+ <div class="panel-heading timeline-heading">
<div class="title">
{{$t('user_card.followers')}}
</div>
</div>
- <div class="panel-body base01-background">
+ <div class="panel-body">
<div class="timeline">
<user-card v-for="follower in followers" :key="follower.id" :user="follower" :showFollows="false"></user-card>
</div>
</div>
</div>
<div class="timeline panel panel-default" v-else-if="viewing == 'friends'">
- <div class="panel-heading timeline-heading base02-background base04">
+ <div class="panel-heading timeline-heading">
<div class="title">
{{$t('user_card.followees')}}
</div>
</div>
- <div class="panel-body base01-background">
+ <div class="panel-body">
<div class="timeline">
<user-card v-for="friend in friends" :key="friend.id" :user="friend" :showFollows="true"></user-card>
</div>
@@ -52,51 +54,69 @@
<script src="./timeline.js"></script>
<style lang="scss">
+@import '../../_variables.scss';
+
+.timeline {
+ .timeline-heading {
+ position: relative;
+ display: flex;
+ }
+
+ .title {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 70%;
+ }
+
+ .loadmore-button {
+ position: absolute;
+ right: 0.6em;
+ font-size: 14px;
- .timeline {
- .timeline-heading {
- position: relative;
- display: flex;
- }
- .title {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 70%;
- }
- .loadmore-button {
- position: absolute;
- right: 0.6em;
- font-size: 14px;
+ min-width: 6em;
+ height: 1.8em;
+ line-height: 100%;
+ }
- min-width: 6em;
- height: 1.8em;
- line-height: 100%;
- }
- .loadmore-text {
- position: absolute;
- right: 0.6em;
- font-size: 14px;
- min-width: 6em;
- border-radius: 5px;
- font-family: sans-serif;
- text-align: center;
- padding: 0 0.5em 0 0.5em;
- opacity: 0.8;
- }
- .error {
- background-color: rgba(255, 48, 16, 0.65);
- }
+ .loadmore-text {
+ position: absolute;
+ right: 0.6em;
+ font-size: 14px;
+ min-width: 6em;
+ font-family: sans-serif;
+ text-align: center;
+ padding: 0 0.5em 0 0.5em;
+ opacity: 0.8;
+ background-color: transparent;
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
}
- .new-status-notification {
- position:relative;
- margin-top: -1px;
- font-size: 1.1em;
- border-width: 1px 0 0 0;
- border-style: solid;
- border-radius: 0 0 10px 10px;
- padding: 10px;
- z-index: 1;
+ .loadmore-error {
+ position: absolute;
+ right: 0.6em;
+ font-size: 14px;
+ min-width: 6em;
+ font-family: sans-serif;
+ text-align: center;
+ padding: 0 0.25em 0 0.25em;
+ margin: 0;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
}
+}
+
+.new-status-notification {
+ position:relative;
+ margin-top: -1px;
+ font-size: 1.1em;
+ border-width: 1px 0 0 0;
+ border-style: solid;
+ border-color: var(--border, $fallback--border);
+ padding: 10px;
+ z-index: 1;
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+}
</style>
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index dd14d1b4..51d6965f 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -1,5 +1,5 @@
<template>
- <div class="card base00-background">
+ <div class="card">
<a href="#">
<img @click.prevent="toggleUserExpanded" class="avatar" :src="user.profile_image_url">
</a>
@@ -7,7 +7,7 @@
<user-card-content :user="user" :switcher="false"></user-card-content>
</div>
<div class="name-and-screen-name" v-else>
- <div class="user-name">
+ <div :title="user.name" class="user-name">
{{ user.name }}
<span class="follows-you" v-if="!userExpanded && showFollows && user.follows_you">
{{ $t('user_card.follows_you') }}
@@ -21,54 +21,58 @@
<script src="./user_card.js"></script>
<style lang="scss">
- .name-and-screen-name {
- margin-left: 0.7em;
- margin-top:0.0em;
- margin-right: 2em;
- text-align: left;
- width: 100%;
- }
+@import '../../_variables.scss';
- .follows-you {
- margin-left: 2em;
- float: right;
- }
+.name-and-screen-name {
+ margin-left: 0.7em;
+ margin-top:0.0em;
+ text-align: left;
+ width: 100%;
+}
- .follows {
+.follows-you {
+ margin-left: 2em;
+ float: right;
+}
- }
+.card {
+ display: flex;
+ flex: 1 0;
+ padding-top: 0.6em;
+ padding-right: 1em;
+ padding-bottom: 0.6em;
+ padding-left: 1em;
+ border-bottom: 1px solid;
+ margin: 0;
+ border-bottom-color: $fallback--border;
+ border-bottom-color: var(--border, $fallback--border);
- .card {
- display: flex;
- flex: 1 0;
- padding-top: 0.6em;
- padding-right: 1em;
- padding-bottom: 0.6em;
- padding-left: 1em;
- border-bottom: 1px solid;
- margin: 0;
- border-bottom-color: inherit;
+ .avatar {
+ margin-top: 0.2em;
+ width:32px;
+ height: 32px;
+ border-radius: $fallback--avatarAltRadius;
+ border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+ }
+}
+.usercard {
+ width: fill-available;
+ margin: 0.2em 0 0.7em 0;
+ border-radius: $fallback--panelRadius;
+ border-radius: var(--panelRadius, $fallback--panelRadius);
+ border-style: solid;
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ border-width: 1px;
+ overflow: hidden;
- .avatar {
- margin-top: 0.2em;
- width:32px;
- height: 32px;
- border-radius: 50%;
- }
+ .panel-heading {
+ background: transparent;
}
- .usercard {
- width: fill-available;
- margin: 0.2em 0 0.7em 0;
- border-radius: 10px;
- border-style: solid;
- border-color: inherit;
- border-width: 1px;
- overflow: hidden;
-
- p {
- margin-bottom: 0;
- }
+ 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
index 32d62ebb..1e8c91de 100644
--- a/src/components/user_card_content/user_card_content.js
+++ b/src/components/user_card_content/user_card_content.js
@@ -1,10 +1,11 @@
+import StillImage from '../still-image/still-image.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js'
export default {
- props: [ 'user', 'switcher' ],
+ props: [ 'user', 'switcher', 'hideBio' ],
computed: {
headingStyle () {
- const color = this.$store.state.config.colors['base00']
+ const color = this.$store.state.config.colors.bg
if (color) {
const rgb = hex2rgb(color)
console.log(rgb)
@@ -14,11 +15,6 @@ export default {
}
}
},
- 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
},
@@ -35,6 +31,9 @@ export default {
return Math.round(this.user.statuses_count / days)
}
},
+ components: {
+ StillImage
+ },
methods: {
followUser () {
const store = this.$store
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index ef000c94..ca8428ca 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -5,43 +5,45 @@
<router-link to='/user-settings' style="float: right; margin-top:16px;" v-if="!isOtherUser">
<i class="icon-cog usersettings"></i>
</router-link>
+ <a :href="user.statusnet_profile_url" target="_blank" style="float: right; margin-top:16px;" v-if="isOtherUser">
+ <i class="icon-link-ext usersettings"></i>
+ </a>
<div class='container'>
<router-link :to="{ name: 'user-profile', params: { id: user.id } }">
- <img :src="user.profile_image_url_original">
+ <StillImage class="avatar" :src="user.profile_image_url_original"/>
</router-link>
- <span class="glyphicon glyphicon-user"></span>
<div class="name-and-screen-name">
- <div class='user-name'>{{user.name}}</div>
+ <div :title="user.name" class='user-name'>{{user.name}}</div>
<router-link :to="{ name: 'user-profile', params: { id: user.id } }">
<div class='user-screen-name'>@{{user.screen_name}}</div>
</router-link>
</div>
</div>
<div v-if="isOtherUser" class="user-interactions">
- <div v-if="user.follows_you && loggedIn" class="following base06">
+ <div v-if="user.follows_you && loggedIn" class="following">
{{ $t('user_card.follows_you') }}
</div>
<div class="follow" v-if="loggedIn">
<span v-if="user.following">
<!--Following them!-->
- <button @click="unfollowUser" class="base04 base00-background pressed">
+ <button @click="unfollowUser" class="pressed">
{{ $t('user_card.following') }}
</button>
</span>
<span v-if="!user.following">
- <button @click="followUser" class="base05 base02-background">
+ <button @click="followUser">
{{ $t('user_card.follow') }}
</button>
</span>
</div>
<div class='mute' v-if='isOtherUser'>
<span v-if='user.muted'>
- <button @click="toggleMute" class="base04 base00-background pressed">
+ <button @click="toggleMute" class="pressed">
{{ $t('user_card.muted') }}
</button>
</span>
<span v-if='!user.muted'>
- <button @click="toggleMute" class="base05 base02-background">
+ <button @click="toggleMute">
{{ $t('user_card.mute') }}
</button>
</span>
@@ -50,19 +52,19 @@
<form method="POST" :action='subscribeUrl'>
<input type="hidden" name="nickname" :value="user.screen_name">
<input type="hidden" name="profile" value="">
- <button click="submit" class="remote-button base05 base02-background">
+ <button click="submit" class="remote-button">
{{ $t('user_card.remote_follow') }}
</button>
</form>
</div>
<div class='block' v-if='isOtherUser && loggedIn'>
<span v-if='user.statusnet_blocking'>
- <button @click="unblockUser" class="base04 base00-background pressed">
+ <button @click="unblockUser" class="pressed">
{{ $t('user_card.blocked') }}
</button>
</span>
<span v-if='!user.statusnet_blocking'>
- <button @click="blockUser" class="base05 base02-background">
+ <button @click="blockUser">
{{ $t('user_card.block') }}
</button>
</span>
@@ -70,25 +72,25 @@
</div>
</div>
</div>
- <div class="panel-body profile-panel-body" :style="bodyStyle">
+ <div class="panel-body profile-panel-body">
<div class="user-counts">
<div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('statuses')" v-if="switcher"><h5 class="base05">{{ $t('user_card.statuses') }}</h5></a>
+ <a href="#" v-on:click.prevent="setProfileView('statuses')" v-if="switcher"><h5>{{ $t('user_card.statuses') }}</h5></a>
<h5 v-else>{{ $t('user_card.statuses') }}</h5>
- <span class="base05">{{user.statuses_count}} <br><span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span></span>
+ <span>{{user.statuses_count}} <br><span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span></span>
</div>
<div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('friends')" v-if="switcher"><h5 class="base05">{{ $t('user_card.followees') }}</h5></a>
+ <a href="#" v-on:click.prevent="setProfileView('friends')" v-if="switcher"><h5>{{ $t('user_card.followees') }}</h5></a>
<h5 v-else>{{ $t('user_card.followees') }}</h5>
- <span class="base05">{{user.friends_count}}</span>
+ <span>{{user.friends_count}}</span>
</div>
<div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('followers')" v-if="switcher"><h5 class="base05">{{ $t('user_card.followers') }}</h5></a>
+ <a href="#" v-on:click.prevent="setProfileView('followers')" v-if="switcher"><h5>{{ $t('user_card.followers') }}</h5></a>
<h5 v-else>{{ $t('user_card.followers') }}</h5>
- <span class="base05">{{user.followers_count}}</span>
+ <span>{{user.followers_count}}</span>
</div>
</div>
- <p>{{user.description}}</p>
+ <p v-if="!hideBio">{{user.description}}</p>
</div>
</div>
</template>
@@ -100,7 +102,8 @@
.profile-panel-background {
background-size: cover;
- border-radius: 10px;
+ border-radius: $fallback--panelRadius;
+ border-radius: var(--panelRadius, $fallback--panelRadius);
.panel-heading {
padding: 0.6em 0em;
@@ -112,39 +115,51 @@
top: -0em;
padding-top: 4em;
word-wrap: break-word;
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%)
}
.user-info {
- color: white;
+ color: white;
padding: 0 16px 16px 16px;
margin-bottom: -4em;
- .usersettings {
- color: white;
- opacity: 0.8;
- }
-
- .container{
+ .container {
padding: 16px 10px 4px 10px;
display: flex;
- flex-wrap: wrap;
- flex-direction: column;
- align-content: flex-start;
- justify-content: center;
max-height: 56px;
overflow: hidden;
+
+ .avatar {
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ flex: 1 0 100%;
+ width: 56px;
+ height: 56px;
+ box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
+ object-fit: cover;
+
+ &.animated::before {
+ display: none;
+ }
+ }
}
- img {
- border-radius: 5px;
- flex: 1 0 100%;
- width: 56px;
- height: 56px;
- box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
- object-fit: cover;
+ &:hover .animated.avatar {
+ canvas {
+ display: none;
+ }
+ img {
+ visibility: visible;
+ }
}
- text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);
+ text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);
+
+ .usersettings {
+ color: #fff;
+ opacity: .8;
+ }
.name-and-screen-name {
display: block;
@@ -152,18 +167,20 @@
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
+ flex: 1 1 0;
}
- .user-name{
- color: white;
- }
+ .user-name{
+ color: white;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
.user-screen-name {
- color: white;
- font-weight: lighter;
- font-size: 15px;
- padding-right: 0.1em;
- flex: 0 0 auto;
+ color: white;
+ font-weight: lighter;
+ font-size: 15px;
+ padding-right: 0.1em;
}
.user-interactions {
@@ -219,23 +236,23 @@
}
.user-counts {
- display: flex;
- line-height:16px;
- padding: 1em 1.5em 0em 1em;
- text-align: center;
+ display: flex;
+ line-height:16px;
+ padding: 1em 1.5em 0em 1em;
+ text-align: center;
}
.user-count {
- flex: 1;
+ flex: 1;
- h5 {
- font-size:1em;
- font-weight: bolder;
- margin: 0 0 0.25em;
- }
- a {
- text-decoration: none;
- }
+ h5 {
+ font-size:1em;
+ font-weight: bolder;
+ margin: 0 0 0.25em;
+ }
+ a {
+ text-decoration: none;
+ }
}
.dailyAvg {
diff --git a/src/components/user_finder/user_finder.vue b/src/components/user_finder/user_finder.vue
index 3c69e3b4..69bd1d21 100644
--- a/src/components/user_finder/user_finder.vue
+++ b/src/components/user_finder/user_finder.vue
@@ -1,13 +1,13 @@
<template>
<span class="user-finder-container">
- <span class="finder-error base05" v-if="error">
+ <span class="alert error" v-if="error">
<i class="icon-cancel user-finder-icon" @click="dismissError"/>
{{$t('finder.error_fetching_user')}}
</span>
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" />
<a href="#" v-if="hidden"><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden"/></a>
<span v-else>
- <input class="user-finder-input base03-border" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/>
+ <input class="user-finder-input" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/>
<i class="icon-cancel user-finder-icon" @click.prevent.stop="toggleHidden"/>
</span>
</span>
@@ -16,27 +16,16 @@
<script src="./user_finder.js"></script>
<style lang="scss">
- .user-finder-container {
- height: 21px;
- max-width: 100%;
- }
+@import '../../_variables.scss';
- .user-finder-icon {
- }
+.user-finder-container {
+ height: 29px;
+ max-width: 100%;
+}
- .user-finder-input {
- border-width: 1px;
- border-style: solid;
- border-color: inherit;
- border-radius: 5px;
- max-width: 80%;
- padding: 0.1em 0.2em 0.2em 0.2em;
- }
+.user-finder-input {
+ max-width: 80%;
+ vertical-align: middle;
+}
- .finder-error {
- background-color: rgba(255, 48, 16, 0.65);
- margin: 0.35em;
- border-radius: 5px;
- padding: 0.25em;
- }
</style>
diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue
index 1a5e20fb..3d4f873d 100644
--- a/src/components/user_panel/user_panel.vue
+++ b/src/components/user_panel/user_panel.vue
@@ -1,8 +1,8 @@
<template>
<div class="user-panel">
<div v-if='user' class="panel panel-default" style="overflow: visible;">
- <user-card-content :user="user" :switcher="false"></user-card-content>
- <div class="panel-footer base00-background">
+ <user-card-content :user="user" :switcher="false" :hideBio="true"></user-card-content>
+ <div class="panel-footer">
<post-status-form v-if='user'></post-status-form>
</div>
</div>
@@ -11,3 +11,11 @@
</template>
<script src="./user_panel.js"></script>
+
+<style lang="scss">
+.user-panel {
+ .profile-panel-background .panel-heading {
+ background: transparent;
+ }
+}
+</style>
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
index 359abfef..838a43ab 100644
--- a/src/components/user_profile/user_profile.vue
+++ b/src/components/user_profile/user_profile.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <div v-if="user" class="user-profile panel panel-default base00-background">
+ <div v-if="user" class="user-profile panel panel-default">
<user-card-content :user="user" :switcher="true"></user-card-content>
</div>
<Timeline :title="$t('user_profile.timeline_title')" :timeline="timeline" :timeline-name="'user'" :user-id="userId"/>
@@ -15,7 +15,8 @@
flex: 2;
flex-basis: 500px;
padding-bottom: 10px;
- border-radius: 10px;
+ .panel-heading {
+ background: transparent;
+ }
}
-
</style>
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index 1ef52bbf..ed1864cc 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -1,16 +1,16 @@
<template>
- <div class="settings panel panel-default base00-background">
- <div class="panel-heading base02-background base04">
+ <div class="settings panel panel-default">
+ <div class="panel-heading">
{{$t('settings.user_settings')}}
</div>
<div class="panel-body profile-edit">
<div class="setting-item">
<h3>{{$t('settings.name_bio')}}</h3>
<p>{{$t('settings.name')}}</p>
- <input class='name-changer base03-border' id='username' v-model="newname"></input>
+ <input class='name-changer' id='username' v-model="newname"></input>
<p>{{$t('settings.bio')}}</p>
- <textarea class="bio base03-border" v-model="newbio"></textarea>
- <button :disabled='newname.length <= 0' class="btn btn-default base05 base02-background" @click="updateProfile">{{$t('general.submit')}}</button>
+ <textarea class="bio" v-model="newbio"></textarea>
+ <button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
</div>
<div class="setting-item">
<h3>{{$t('settings.avatar')}}</h3>
@@ -22,8 +22,8 @@
<div>
<input type="file" @change="uploadFile(0, $event)" ></input>
</div>
- <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>
+ <i class="icon-spin4 animate-spin" v-if="uploading[0]"></i>
+ <button class="btn btn-default" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button>
</div>
<div class="setting-item">
<h3>{{$t('settings.profile_banner')}}</h3>
@@ -35,8 +35,8 @@
<div>
<input type="file" @change="uploadFile(1, $event)" ></input>
</div>
- <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>
+ <i class=" icon-spin4 animate-spin uploading" v-if="uploading[1]"></i>
+ <button class="btn btn-default" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button>
</div>
<div class="setting-item">
<h3>{{$t('settings.profile_background')}}</h3>
@@ -46,8 +46,8 @@
<div>
<input type="file" @change="uploadFile(2, $event)" ></input>
</div>
- <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>
+ <i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
+ <button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
</div>
<div class="setting-item" v-if="pleromaBackend">
<h3>{{$t('settings.follow_import')}}</h3>
@@ -55,8 +55,8 @@
<form v-model="followImportForm">
<input type="file" ref="followlist" v-on:change="followListChange"></input>
</form>
- <i class="base09 icon-spin4 animate-spin uploading" v-if="uploading[3]"></i>
- <button class="btn btn-default base05 base02-background" v-else @click="importFollows">{{$t('general.submit')}}</button>
+ <i class=" icon-spin4 animate-spin uploading" v-if="uploading[3]"></i>
+ <button class="btn btn-default" v-else @click="importFollows">{{$t('general.submit')}}</button>
<div v-if="followsImported">
<i class="icon-cross" @click="dismissImported"></i>
<p>{{$t('settings.follows_imported')}}</p>
@@ -75,24 +75,16 @@
<style lang="scss">
.profile-edit {
- .name-changer {
- border-width: 1px;
- border-style: solid;
- border-radius: 5px;
- padding: 0.2em 0.2em 0.2em 0.2em;
- }
- .name-submit {
- padding: 0.2em 0.5em 0.2em 0.5em;
- }
.bio {
- border-width: 1px;
- border-style: solid;
- border-radius: 5px;
margin: 0;
}
+
+ input[type=file] {
+ padding: 5px;
+ }
+
.banner {
max-width: 400px;
- border-radius: 5px;
}
.uploading {
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index a2ce3dff..7e17c931 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -20,14 +20,17 @@ const de = {
muted: 'Stummgeschaltet',
followers: 'Folgende',
followees: 'Folgt',
- per_day: 'pro Tag'
+ per_day: 'pro Tag',
+ remote_follow: 'Remote Follow'
},
timeline: {
show_new: 'Zeige Neuere',
error_fetching: 'Fehler beim Laden',
up_to_date: 'Aktuell',
load_older: 'Lade ältere Beiträge',
- conversation: 'Unterhaltung'
+ conversation: 'Unterhaltung',
+ collapse: 'Einklappen',
+ repeated: 'wiederholte'
},
settings: {
user_settings: 'Benutzereinstellungen',
@@ -45,17 +48,28 @@ const de = {
settings: 'Einstellungen',
theme: 'Farbschema',
presets: 'Voreinstellungen',
- theme_help: 'Benutze HTML Farbcodes (#aabbcc) um dein Farbschema anzupassen.',
+ theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen.',
background: 'Hintergrund',
foreground: 'Vordergrund',
text: 'Text',
links: 'Links',
+ cBlue: 'Blau (Antworten, Folgt dir)',
+ cRed: 'Rot (Abbrechen)',
+ cOrange: 'Orange (Favorisieren)',
+ cGreen: 'Grün (Retweet)',
+ btnRadius: 'Buttons',
+ panelRadius: 'Panel',
+ avatarRadius: 'Avatare',
+ avatarAltRadius: 'Avatare (Benachrichtigungen)',
+ tooltipRadius: 'Tooltips/Warnungen',
+ attachmentRadius: 'Anhänge',
filtering: 'Filter',
filtering_explanation: 'Alle Beiträge die diese Wörter enthalten werden ausgeblendet. Ein Wort pro Zeile.',
attachments: 'Anhänge',
- hide_attachments_in_tl: 'Anhänge in der Timeline ausblenden',
+ hide_attachments_in_tl: 'Anhänge in der Zeitleiste ausblenden',
hide_attachments_in_convo: 'Anhänge in Unterhaltungen ausblenden',
- nsfw_clickthrough: 'Aktiviere ausblendbares Overlay für als NSFW markierte Anhänge',
+ nsfw_clickthrough: 'Aktiviere ausblendbares Overlay für Anhänge, die als NSFW markiert sind',
+ stop_gifs: 'Play-on-hover GIFs',
autoload: 'Aktiviere automatisches Laden von älteren Beiträgen beim scrollen',
streaming: 'Aktiviere automatisches Laden (Streaming) von neuen Beiträgen',
reply_link_preview: 'Aktiviere reply-link Vorschau bei Maus-Hover',
@@ -67,7 +81,9 @@ const de = {
notifications: {
notifications: 'Benachrichtigungen',
read: 'Gelesen!',
- followed_you: 'folgt dir'
+ followed_you: 'folgt dir',
+ favorited_you: 'favorisierte deine Nachricht',
+ repeated_you: 'wiederholte deine Nachricht'
},
login: {
login: 'Anmelden',
@@ -94,6 +110,9 @@ const de = {
general: {
submit: 'Absenden',
apply: 'Anwenden'
+ },
+ user_profile: {
+ timeline_title: 'Beiträge'
}
}
@@ -120,7 +139,9 @@ const fi = {
error_fetching: 'Virhe ladatessa viestejä',
up_to_date: 'Ajantasalla',
load_older: 'Lataa vanhempia viestejä',
- conversation: 'Keskustelu'
+ conversation: 'Keskustelu',
+ collapse: 'Sulje',
+ repeated: 'toisti'
},
settings: {
user_settings: 'Käyttäjän asetukset',
@@ -156,7 +177,9 @@ const fi = {
notifications: {
notifications: 'Ilmoitukset',
read: 'Lue!',
- followed_you: 'seuraa sinua'
+ followed_you: 'seuraa sinua',
+ favorited_you: 'tykkäsi viestistäsi',
+ repeated_you: 'toisti viestisi'
},
login: {
login: 'Kirjaudu sisään',
@@ -216,7 +239,9 @@ const en = {
error_fetching: 'Error fetching updates',
up_to_date: 'Up-to-date',
load_older: 'Load older statuses',
- conversation: 'Conversation'
+ conversation: 'Conversation',
+ collapse: 'Collapse',
+ repeated: 'repeated'
},
settings: {
user_settings: 'User Settings',
@@ -234,29 +259,43 @@ const en = {
settings: 'Settings',
theme: 'Theme',
presets: 'Presets',
- theme_help: 'Use hex color codes (#aabbcc) to customize your color theme.',
+ theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.',
+ radii_help: 'Set up interface edge rounding (in pixels)',
background: 'Background',
foreground: 'Foreground',
text: 'Text',
links: 'Links',
+ cBlue: 'Blue (Reply, follow)',
+ cRed: 'Red (Cancel)',
+ cOrange: 'Orange (Favorite)',
+ cGreen: 'Green (Retweet)',
+ btnRadius: 'Buttons',
+ panelRadius: 'Panels',
+ avatarRadius: 'Avatars',
+ avatarAltRadius: 'Avatars (Notifications)',
+ tooltipRadius: 'Tooltips/alerts',
+ attachmentRadius: 'Attachments',
filtering: 'Filtering',
filtering_explanation: 'All statuses containing these words will be muted, one per line',
attachments: 'Attachments',
hide_attachments_in_tl: 'Hide attachments in timeline',
hide_attachments_in_convo: 'Hide attachments in conversations',
nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding',
+ stop_gifs: 'Play-on-hover GIFs',
autoload: 'Enable automatic loading when scrolled to the bottom',
streaming: 'Enable automatic streaming of new posts when scrolled to the top',
reply_link_preview: 'Enable reply-link preview on mouse hover',
follow_import: 'Follow import',
- import_followers_from_a_csv_file: 'Import followers from a csv file',
+ import_followers_from_a_csv_file: 'Import follows from a csv file',
follows_imported: 'Follows imported! Processing them will take a while.',
follow_import_error: 'Error importing followers'
},
notifications: {
notifications: 'Notifications',
read: 'Read!',
- followed_you: 'followed you'
+ followed_you: 'followed you',
+ favorited_you: 'favorited your status',
+ repeated_you: 'repeated your status'
},
login: {
login: 'Log in',
@@ -539,9 +578,13 @@ const ro = {
}
const ja = {
+ chat: {
+ title: 'チャット'
+ },
nav: {
+ chat: 'ローカルチャット',
timeline: 'タイムライン',
- mentions: '通知',
+ mentions: 'メンション',
public_tl: '公開タイムライン',
twkn: '接続しているすべてのネットワーク'
},
@@ -549,22 +592,28 @@ const ja = {
follows_you: 'フォローされました!',
following: 'フォロー中!',
follow: 'フォロー',
- statuses: 'ステータス',
+ blocked: 'ブロック済み!',
+ block: 'ブロック',
+ statuses: '投稿',
mute: 'ミュート',
muted: 'ミュート済み',
followers: 'フォロワー',
followees: 'フォロー',
- per_day: '/日'
+ per_day: '/日',
+ remote_follow: 'リモートフォロー'
},
timeline: {
- show_new: '新しいものを表示',
- error_fetching: '更新の取得中にエラーが発生しました',
+ show_new: '更新',
+ error_fetching: '更新の取得中にエラーが発生しました。',
up_to_date: '最新',
- load_older: '古いステータスを読み込む'
+ load_older: '古い投稿を読み込む',
+ conversation: '会話',
+ collapse: '折り畳む',
+ repeated: 'リピート'
},
settings: {
user_settings: 'ユーザー設定',
- name_bio: '名前 & プロフィール',
+ name_bio: '名前とプロフィール',
name: '名前',
bio: 'プロフィール',
avatar: 'アバター',
@@ -577,23 +626,48 @@ const ja = {
set_new_profile_background: '新しいプロフィールの背景を設定する',
settings: '設定',
theme: 'テーマ',
+ presets: 'プリセット',
+ theme_help: '16進数カラーコード (#aabbcc) を使用してカラーテーマをカスタマイズ出来ます。',
+ radii_help: 'インターフェースの縁の丸さを設定する。',
+ background: '背景',
+ foreground: '前景',
+ text: '文字',
+ links: 'リンク',
+ cBlue: '青 (返信, フォロー)',
+ cRed: '赤 (キャンセル)',
+ cOrange: 'オレンジ (お気に入り)',
+ cGreen: '緑 (リツイート)',
+ btnRadius: 'ボタン',
+ panelRadius: 'パネル',
+ avatarRadius: 'アバター',
+ avatarAltRadius: 'アバター (通知)',
+ tooltipRadius: 'ツールチップ/アラート',
+ attachmentRadius: 'ファイル',
filtering: 'フィルタリング',
- filtering_explanation: 'これらの単語を含むすべてのものはミュートされます、1行に1つのワードを入力してください',
- attachments: '添付ファイル',
- hide_attachments_in_tl: 'タイムラインの添付ファイルを隠す',
- hide_attachments_in_convo: '会話の中の添付ファイルを隠す',
- nsfw_clickthrough: 'NSFWファイルの非表示を有効にする',
- autoload: '下にスクロールした時に自動で読み込むようにする',
- reply_link_preview: 'マウスカーソルを重ねたときに返信リンクプレビューを表示するようにする'
+ filtering_explanation: 'これらの単語を含むすべてのものがミュートされます。1行に1つの単語を入力してください。',
+ attachments: 'ファイル',
+ hide_attachments_in_tl: 'タイムラインのファイルを隠す。',
+ hide_attachments_in_convo: '会話の中のファイルを隠す。',
+ nsfw_clickthrough: 'NSFWファイルの非表示を有効にする。',
+ stop_gifs: 'カーソルを重ねた時にGIFを再生する。',
+ autoload: '下にスクロールした時に自動で読み込むようにする。',
+ streaming: '上までスクロールした時に自動でストリーミングされるようにする。',
+ reply_link_preview: 'マウスカーソルを重ねた時に返信のプレビューを表示するようにする。',
+ follow_import: 'フォローインポート',
+ import_followers_from_a_csv_file: 'CSVファイルからフォローをインポートする。',
+ follows_imported: 'フォローがインポートされました!処理に少し時間がかかるかもしれません。',
+ follow_import_error: 'フォロワーのインポート中にエラーが発生しました。'
},
notifications: {
notifications: '通知',
read: '読んだ!',
- followed_you: 'フォローされました'
+ followed_you: 'フォローされました',
+ favorited_you: 'あなたの投稿がお気に入りされました',
+ repeated_you: 'あなたの投稿がリピートされました'
},
login: {
login: 'ログイン',
- username: 'ユーザーネーム',
+ username: 'ユーザー名',
password: 'パスワード',
register: '登録',
logout: 'ログアウト'
@@ -607,43 +681,51 @@ const ja = {
},
post_status: {
posting: '投稿',
- default: 'ちょうど羽田に着陸しました'
+ default: 'ちょうどL.A.に着陸しました。'
},
finder: {
find_user: 'ユーザー検索',
error_fetching_user: 'ユーザー検索でエラーが発生しました'
},
general: {
- submit: '送信'
+ submit: '送信',
+ apply: '適用'
+ },
+ user_profile: {
+ timeline_title: 'ユーザータイムライン'
}
}
const fr = {
nav: {
+ chat: 'Chat local',
timeline: 'Journal',
mentions: 'Notifications',
public_tl: 'Statuts locaux',
twkn: 'Le réseau connu'
},
user_card: {
- follows_you: 'Vous suit!',
- following: 'Suivi!',
+ follows_you: 'Vous suit !',
+ following: 'Suivi !',
follow: 'Suivre',
blocked: 'Bloqué',
block: 'Bloquer',
statuses: 'Statuts',
- mute: 'En sourdine',
- muted: 'Mis en sourdine',
+ mute: 'Mettre en muet',
+ muted: 'Mis en muet',
followers: 'Vous suivent',
followees: 'Suivis',
- per_day: 'par jour'
+ per_day: 'par jour',
+ remote_follow: 'Suivre d\'une autre instance'
},
timeline: {
show_new: 'Afficher plus',
error_fetching: 'Erreur en cherchant des mises à jours',
up_to_date: 'À jour',
load_older: 'Afficher plus',
- conversation: 'Conversation'
+ conversation: 'Conversation',
+ collapse: 'Fermer',
+ repeated: 'a partagé'
},
settings: {
user_settings: 'Paramètres utilisateur',
@@ -653,26 +735,51 @@ const fr = {
avatar: 'Avatar',
current_avatar: 'Votre avatar',
set_new_avatar: 'Changer d\'avatar',
- profile_banner: 'Bannière du Profil',
+ profile_banner: 'Bannière du profil',
current_profile_banner: 'Bannière du profil',
set_new_profile_banner: 'Changer de bannière',
profile_background: 'Image de fond',
- set_new_profile_background: 'Changer l\'image de fond',
+ set_new_profile_background: 'Changer d\'image de fond',
settings: 'Paramètres',
theme: 'Thème',
filtering: 'Filtre',
- filtering_explanation: 'Tout les statuts contenant ces mots vont être mis sous silence, un mot par ligne.',
+ filtering_explanation: 'Tout les statuts contenant ces mots vont être cachés, un mot par ligne.',
attachments: 'Pièces jointes',
hide_attachments_in_tl: 'Cacher les pièces jointes dans le journal',
hide_attachments_in_convo: 'Cacher les pièces jointes dans les conversations',
nsfw_clickthrough: 'Activer le clic pour afficher les images marquées comme contenu adulte ou sensible',
autoload: 'Activer le chargement automatique une fois le bas de la page atteint',
- reply_link_preview: 'Activer un aperçu sur passage de la souris'
+ reply_link_preview: 'Activer un aperçu d\'une réponse sur passage de la souris',
+ presets: 'Thèmes prédéfinis',
+ theme_help: 'Utilisez les codes de couleur hexadécimaux (#aabbcc) pour customiser les couleurs de votre thème.',
+ background: 'Arrière plan',
+ foreground: 'Premier plan',
+ text: 'Texte',
+ links: 'Liens',
+ streaming: 'Active le défilement automatique de nouveaux statuts lorsqu\'on est au haut de la page',
+ follow_import: 'Importer ses abonnements',
+ import_followers_from_a_csv_file: 'Importer ses abonnements depuis un fichier csv',
+ follows_imported: 'Abonnements importés ! Le traitement peut prendre un moment.',
+ follow_import_error: 'Erreur lors de l\'importation des abonnements.',
+ cBlue: 'Bleu (Répondre, suivre)',
+ cRed: 'Rouge (Annuler)',
+ cOrange: 'Orange (Aimer)',
+ cGreen: 'Vert (Partager)',
+ btnRadius: 'Boutons',
+ panelRadius: 'Fenêtres',
+ avatarRadius: 'Avatars',
+ avatarAltRadius: 'Avatars (Notifications)',
+ tooltipRadius: 'Info-bulles/alertes ',
+ attachmentRadius: 'Pièces jointes',
+ radii_help: 'Mettre en place l\'arondissement des coins de l\'interface (en pixels)',
+ stop_gifs: 'Passer la souris sur un GIF pour l\'animer'
},
notifications: {
- notifications: 'Notfications',
- read: 'Lu!',
- followed_you: 'vous a suivi'
+ notifications: 'Notifications',
+ read: 'Lu !',
+ followed_you: 'vous a suivi',
+ favorited_you: 'a aimé votre statut',
+ repeated_you: 'a partagé votre statut'
},
login: {
login: 'Connexion',
@@ -683,10 +790,10 @@ const fr = {
},
registration: {
registration: 'Inscription',
- fullname: 'Nom complet',
- email: 'Adresse courriel',
+ fullname: 'Nom affiché',
+ email: 'Adresse email',
bio: 'Biographie',
- password_confirm: 'Confirmer le mot de passe'
+ password_confirm: 'Confirmez le mot de passe'
},
post_status: {
posting: 'Envoi en cours',
@@ -694,10 +801,14 @@ const fr = {
},
finder: {
find_user: 'Chercher un utilisateur',
- error_fetching_user: 'Une erreur est survenue pendant la recherche d\'un utilisateur'
+ error_fetching_user: 'Une erreur est survenue lors de la recherche de l\'utilisateur'
},
general: {
- submit: 'Envoyer'
+ submit: 'Envoyer',
+ apply: 'Appliquer'
+ },
+ user_profile: {
+ timeline_title: 'Journal de l\'utilisateur'
}
}
@@ -759,8 +870,131 @@ const it = {
}
}
+const oc = {
+ chat: {
+ title: 'Messatjariá'
+ },
+ nav: {
+ chat: 'Chat local',
+ timeline: 'Flux d’actualitat',
+ mentions: 'Notificacions',
+ public_tl: 'Estatuts locals',
+ twkn: 'Lo malhum conegut'
+ },
+ user_card: {
+ follows_you: 'Vos sèc !',
+ following: 'Seguit !',
+ follow: 'Seguir',
+ blocked: 'Blocat',
+ block: 'Blocar',
+ statuses: 'Estatuts',
+ mute: 'Amagar',
+ muted: 'Amagat',
+ followers: 'Seguidors',
+ followees: 'Abonaments',
+ per_day: 'per jorn',
+ remote_follow: 'Seguir a distància'
+ },
+ timeline: {
+ show_new: 'Ne veire mai',
+ error_fetching: 'Error en cercant de mesas a jorn',
+ up_to_date: 'Actualizat',
+ load_older: 'Ne veire mai',
+ conversation: 'Conversacion',
+ collapse: 'Tampar',
+ repeated: 'repetit'
+ },
+ settings: {
+ user_settings: 'Paramètres utilizaire',
+ name_bio: 'Nom & Bio',
+ name: 'Nom',
+ bio: 'Biografia',
+ avatar: 'Avatar',
+ current_avatar: 'Vòstre avatar actual',
+ set_new_avatar: 'Cambiar l’avatar',
+ profile_banner: 'Bandièra del perfil',
+ current_profile_banner: 'Bandièra actuala del perfil',
+ set_new_profile_banner: 'Cambiar de bandièra',
+ profile_background: 'Imatge de fons',
+ set_new_profile_background: 'Cambiar l’imatge de fons',
+ settings: 'Paramètres',
+ theme: 'Tèma',
+ presets: 'Pre-enregistrats',
+ theme_help: 'Emplegatz los còdis de color hex (#rrggbb) per personalizar vòstre tèma de color.',
+ radii_help: 'Configurar los caires arredondits de l’interfàcia (en pixèls)',
+ background: 'Rèire plan',
+ foreground: 'Endavant',
+ text: 'Tèxte',
+ links: 'Ligams',
+ cBlue: 'Blau (Respondre, seguir)',
+ cRed: 'Roge (Anullar)',
+ cOrange: 'Irange (Metre en favorit)',
+ cGreen: 'Verd (Repartajar)',
+ btnRadius: 'Botons',
+ panelRadius: 'Panèls',
+ avatarRadius: 'Avatars',
+ avatarAltRadius: 'Avatars (Notificacions)',
+ tooltipRadius: 'Astúcias/Alèrta',
+ attachmentRadius: 'Pèças juntas',
+ filtering: 'Filtre',
+ filtering_explanation: 'Totes los estatuts amb aqueles mots seràn en silenci, un mot per linha.',
+ attachments: 'Pèças juntas',
+ hide_attachments_in_tl: 'Rescondre las pèças juntas',
+ hide_attachments_in_convo: 'Rescondre las pèças juntas dins las conversacions',
+ nsfw_clickthrough: 'Activar lo clic per mostrar los imatges marcats coma pels adults o sensibles',
+ stop_gifs: 'Lançar los GIFs al subrevòl',
+ autoload: 'Activar lo cargament automatic un còp arribat al cap de la pagina',
+ streaming: 'Activar lo cargament automatic dels novèls estatus en anar amont',
+ reply_link_preview: 'Activar l’apercebut en passar la mirga',
+ follow_import: 'Importar los abonaments',
+ import_followers_from_a_csv_file: 'Importar los seguidors d’un fichièr csv',
+ follows_imported: 'Seguidors importats. Lo tractament pòt trigar una estona.',
+ follow_import_error: 'Error en important los seguidors'
+ },
+ notifications: {
+ notifications: 'Notficacions',
+ read: 'Legit !',
+ followed_you: 'vos a seguit',
+ favorited_you: 'a aimat vòstre estatut',
+ repeated_you: 'a repetit your vòstre estatut'
+ },
+ login: {
+ login: 'Connexion',
+ username: 'Nom d’utilizaire',
+ password: 'Senhal',
+ register: 'Se marcar',
+ logout: 'Desconnexion'
+ },
+ registration: {
+ registration: 'Inscripcion',
+ fullname: 'Nom complèt',
+ email: 'Adreça de corrièl',
+ bio: 'Biografia',
+ password_confirm: 'Confirmar lo senhal'
+ },
+ post_status: {
+ posting: 'Mandadís',
+ default: 'Escrivètz aquí vòstre estatut.'
+ },
+ finder: {
+ find_user: 'Cercar un utilizaire',
+ error_fetching_user: 'Error pendent la recèrca d’un utilizaire'
+ },
+ general: {
+ submit: 'Mandar',
+ apply: 'Aplicar'
+ },
+ user_profile: {
+ timeline_title: 'Flux a l’utilizaire'
+ }
+}
+
const pl = {
+ chat: {
+ title: 'Czat'
+ },
nav: {
+ chat: 'Lokalny czat',
timeline: 'Oś czasu',
mentions: 'Wzmianki',
public_tl: 'Publiczna oś czasu',
@@ -777,14 +1011,17 @@ const pl = {
muted: 'Wyciszony',
followers: 'Obserwujący',
followees: 'Obserwowani',
- per_day: 'dziennie'
+ per_day: 'dziennie',
+ remote_follow: 'Zdalna obserwacja'
},
timeline: {
show_new: 'Pokaż nowe',
error_fetching: 'Błąd pobierania',
up_to_date: 'Na bieżąco',
load_older: 'Załaduj starsze statusy',
- conversation: 'Rozmowa'
+ conversation: 'Rozmowa',
+ collapse: 'Zwiń',
+ repeated: 'powtórzono'
},
settings: {
user_settings: 'Ustawienia użytkownika',
@@ -794,26 +1031,51 @@ const pl = {
avatar: 'Awatar',
current_avatar: 'Twój obecny awatar',
set_new_avatar: 'Ustaw nowy awatar',
- profile_banner: 'Banner profilui',
+ profile_banner: 'Banner profilu',
current_profile_banner: 'Twój obecny banner profilu',
set_new_profile_banner: 'Ustaw nowy banner profilu',
profile_background: 'Tło profilu',
set_new_profile_background: 'Ustaw nowe tło profilu',
settings: 'Ustawienia',
theme: 'Motyw',
+ presets: 'Gotowe motywy',
+ theme_help: 'Użyj kolorów w notacji szesnastkowej (#rrggbb), by stworzyć swój motyw.',
+ radii_help: 'Ustaw zaokrąglenie krawędzi interfejsu (w pikselach)',
+ background: 'Tło',
+ foreground: 'Pierwszy plan',
+ text: 'Tekst',
+ links: 'Łącza',
+ cBlue: 'Niebieski (odpowiedz, obserwuj)',
+ cRed: 'Czerwony (anuluj)',
+ cOrange: 'Pomarańczowy (ulubione)',
+ cGreen: 'Zielony (powtórzenia)',
+ btnRadius: 'Przyciski',
+ panelRadius: 'Panele',
+ avatarRadius: 'Awatary',
+ avatarAltRadius: 'Awatary (powiadomienia)',
+ tooltipRadius: 'Etykiety/alerty',
+ attachmentRadius: 'Załączniki',
filtering: 'Filtrowanie',
filtering_explanation: 'Wszystkie statusy zawierające te słowa będą wyciszone. Jedno słowo na linijkę',
attachments: 'Załączniki',
hide_attachments_in_tl: 'Ukryj załączniki w osi czasu',
hide_attachments_in_convo: 'Ukryj załączniki w rozmowach',
nsfw_clickthrough: 'Włącz domyślne ukrywanie załączników o treści nieprzyzwoitej (NSFW)',
+ stop_gifs: 'Odtwarzaj GIFy po najechaniu kursorem',
autoload: 'Włącz automatyczne ładowanie po przewinięciu do końca strony',
- reply_link_preview: 'Włącz dymek z podglądem postu po najechaniu na znak odpowiedzi'
+ streaming: 'Włącz automatycznie strumieniowanie nowych postów gdy na początku strony',
+ reply_link_preview: 'Włącz dymek z podglądem postu po najechaniu na znak odpowiedzi',
+ follow_import: 'Import obserwowanych',
+ import_followers_from_a_csv_file: 'Importuj obserwowanych z pliku CSV',
+ follows_imported: 'Obserwowani zaimportowani! Przetwarzanie może trochę potrwać.',
+ follow_import_error: 'Błąd przy importowaniu obserwowanych'
},
notifications: {
notifications: 'Powiadomienia',
read: 'Przeczytane!',
- followed_you: 'obserwuje cię'
+ followed_you: 'obserwuje cię',
+ favorited_you: 'dodał twój status do ulubionych',
+ repeated_you: 'powtórzył twój status'
},
login: {
login: 'Zaloguj',
@@ -824,7 +1086,7 @@ const pl = {
},
registration: {
registration: 'Rejestracja',
- fullname: 'Wyświetlane imię',
+ fullname: 'Wyświetlana nazwa profilu',
email: 'Email',
bio: 'Bio',
password_confirm: 'Potwierdzenie hasła'
@@ -838,7 +1100,11 @@ const pl = {
error_fetching_user: 'Błąd przy pobieraniu profilu'
},
general: {
- submit: 'Wyślij'
+ submit: 'Wyślij',
+ apply: 'Zastosuj'
+ },
+ user_profile: {
+ timeline_title: 'Oś czasu użytkownika'
}
}
@@ -890,7 +1156,7 @@ const es = {
settings: 'Ajustes',
theme: 'Tema',
presets: 'Por defecto',
- theme_help: 'Use códigos de color hexadecimales (#aabbcc) para personalizar su tema de colores.',
+ theme_help: 'Use códigos de color hexadecimales (#rrggbb) para personalizar su tema de colores.',
background: 'Segundo plano',
foreground: 'Primer plano',
text: 'Texto',
@@ -960,11 +1226,12 @@ const pt = {
blocked: 'Bloqueado!',
block: 'Bloquear',
statuses: 'Postagens',
- mute: 'Mutar',
- muted: 'Mudo',
+ mute: 'Silenciar',
+ muted: 'Silenciado',
followers: 'Seguidores',
followees: 'Seguindo',
- per_day: 'por dia'
+ per_day: 'por dia',
+ remote_follow: 'Seguidor Remoto'
},
timeline: {
show_new: 'Mostrar novas',
@@ -980,16 +1247,16 @@ const pt = {
bio: 'Biografia',
avatar: 'Avatar',
current_avatar: 'Seu avatar atual',
- set_new_avatar: 'Mudar avatar',
+ set_new_avatar: 'Alterar avatar',
profile_banner: 'Capa de perfil',
current_profile_banner: 'Sua capa de perfil atual',
- set_new_profile_banner: 'Mudar capa de perfil',
+ set_new_profile_banner: 'Alterar capa de perfil',
profile_background: 'Plano de fundo de perfil',
- set_new_profile_background: 'Mudar o plano de fundo de perfil',
+ set_new_profile_background: 'Alterar o plano de fundo de perfil',
settings: 'Configurações',
theme: 'Tema',
presets: 'Predefinições',
- theme_help: 'Use cores em códigos hexadecimais (#aabbcc) para personalizar seu esquema de cores.',
+ theme_help: 'Use cores em código hexadecimal (#rrggbb) para personalizar seu esquema de cores.',
background: 'Plano de Fundo',
foreground: 'Primeiro Plano',
text: 'Texto',
@@ -1004,9 +1271,9 @@ const pt = {
streaming: 'Habilitar o fluxo automático de postagens quando ao topo da página',
reply_link_preview: 'Habilitar a pré-visualização de link de respostas ao passar o mouse.',
follow_import: 'Importar seguidas',
- import_followers_from_a_csv_file: 'Importe os perfis que tu segues apartir de um arquivo CSV',
- follows_imported: 'Seguidas importadas! O processamento das mesmas pode demorar um pouco.',
- follow_import_error: 'Erro ao importar seguidas'
+ import_followers_from_a_csv_file: 'Importe seguidores a partir de um arquivo CSV',
+ follows_imported: 'Seguidores importados! O processamento pode demorar um pouco.',
+ follow_import_error: 'Erro ao importar seguidores'
},
notifications: {
notifications: 'Notificações',
@@ -1023,7 +1290,7 @@ const pt = {
registration: {
registration: 'Registro',
fullname: 'Nome para exibição',
- email: 'Correio eletônico',
+ email: 'Correio eletrônico',
bio: 'Biografia',
password_confirm: 'Confirmação de senha'
},
@@ -1071,7 +1338,9 @@ const ru = {
error_fetching: 'Ошибка при обновлении',
up_to_date: 'Обновлено',
load_older: 'Загрузить старые статусы',
- conversation: 'Разговор'
+ conversation: 'Разговор',
+ collapse: 'Свернуть',
+ repeated: 'повторил(а)'
},
settings: {
user_settings: 'Настройки пользователя',
@@ -1089,16 +1358,28 @@ const ru = {
settings: 'Настройки',
theme: 'Тема',
presets: 'Пресеты',
- theme_help: 'Используйте шестнадцатеричные коды цветов (#aabbcc) для настройки темы.',
+ theme_help: 'Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.',
+ radii_help: 'Округление краёв элементов интерфейса (в пикселях)',
background: 'Фон',
foreground: 'Передний план',
text: 'Текст',
links: 'Ссылки',
+ cBlue: 'Ответить, читать',
+ cRed: 'Отменить',
+ cOrange: 'Нравится',
+ cGreen: 'Повторить',
+ btnRadius: 'Кнопки',
+ panelRadius: 'Панели',
+ avatarRadius: 'Аватары',
+ avatarAltRadius: 'Аватары в уведомлениях',
+ tooltipRadius: 'Всплывающие подсказки/уведомления',
+ attachmentRadius: 'Прикреплённые файлы',
filtering: 'Фильтрация',
filtering_explanation: 'Все статусы, содержащие данные слова, будут игнорироваться, по одному в строке',
attachments: 'Вложения',
hide_attachments_in_tl: 'Прятать вложения в ленте',
hide_attachments_in_convo: 'Прятать вложения в разговорах',
+ stop_gifs: 'Проигрывать GIF анимации только при наведении',
nsfw_clickthrough: 'Включить скрытие NSFW вложений',
autoload: 'Включить автоматическую загрузку при прокрутке вниз',
streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх',
@@ -1111,7 +1392,9 @@ const ru = {
notifications: {
notifications: 'Уведомления',
read: 'Прочесть',
- followed_you: 'начал читать вас'
+ followed_you: 'начал(а) читать вас',
+ favorited_you: 'нравится ваш статус',
+ repeated_you: 'повторил(а) ваш статус'
},
login: {
login: 'Войти',
@@ -1154,6 +1437,7 @@ const messages = {
ja,
fr,
it,
+ oc,
pl,
es,
pt,
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 18191424..bd52f161 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -1,7 +1,23 @@
-import { includes, remove, slice, sortBy, toInteger, each, find, flatten, maxBy, last, merge, max, isArray } from 'lodash'
+import { includes, remove, slice, sortBy, toInteger, each, find, flatten, maxBy, minBy, merge, last, isArray } from 'lodash'
import apiService from '../services/api/api.service.js'
// import parse from '../services/status_parser/status_parser.js'
+const emptyTl = () => ({
+ statuses: [],
+ statusesObject: {},
+ faves: [],
+ visibleStatuses: [],
+ visibleStatusesObject: {},
+ newStatusCount: 0,
+ maxId: 0,
+ minVisibleId: 0,
+ loading: false,
+ followers: [],
+ friends: [],
+ viewing: 'statuses',
+ flushMarker: 0
+})
+
export const defaultState = {
allStatuses: [],
allStatusesObject: {},
@@ -10,96 +26,12 @@ export const defaultState = {
favorites: new Set(),
error: false,
timelines: {
- mentions: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- },
- public: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- },
- user: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- },
- publicAndExternal: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- },
- friends: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- },
- tag: {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- }
+ mentions: emptyTl(),
+ public: emptyTl(),
+ user: emptyTl(),
+ publicAndExternal: emptyTl(),
+ friends: emptyTl(),
+ tag: emptyTl()
}
}
@@ -112,6 +44,9 @@ export const prepareStatus = (status) => {
// Parse nsfw tags
if (status.nsfw === undefined) {
status.nsfw = isNsfw(status)
+ if (status.retweeted_status) {
+ status.retweeted_status.nsfw = status.nsfw
+ }
}
// Set deleted flag
@@ -175,7 +110,6 @@ const sortTimeline = (timeline) => {
timeline.visibleStatuses = sortBy(timeline.visibleStatuses, ({id}) => -id)
timeline.statuses = sortBy(timeline.statuses, ({id}) => -id)
timeline.minVisibleId = (last(timeline.visibleStatuses) || {}).id
-
return timeline
}
@@ -189,10 +123,11 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
const allStatusesObject = state.allStatusesObject
const timelineObject = state.timelines[timeline]
- // Set the maxId to the new id if it's larger.
- const updateMaxId = ({id}) => {
- if (!timeline || noIdUpdate) { return false }
- timelineObject.maxId = max([id, timelineObject.maxId])
+ const maxNew = statuses.length > 0 ? maxBy(statuses, 'id').id : 0
+ const older = timeline && maxNew < timelineObject.maxId
+
+ if (timeline && !noIdUpdate && statuses.length > 0 && !older) {
+ timelineObject.maxId = maxNew
}
const addStatus = (status, showImmediately, addToTimeline = true) => {
@@ -200,8 +135,6 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
status = result.item
if (result.new) {
- updateMaxId(status)
-
if (statusType(status) === 'retweet' && status.retweeted_status.user.id === user.id) {
addNotification({ type: 'repeat', status: status.retweeted_status, action: status })
}
@@ -246,7 +179,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
const addNotification = ({type, status, action}) => {
// Only add a new notification if we don't have one for the same action
if (!find(state.notifications, (oldNotification) => oldNotification.action.id === action.id)) {
- state.notifications.push({type, status, action, seen: false})
+ state.notifications.push({ type, status, action, seen: false })
if ('Notification' in window && window.Notification.permission === 'granted') {
const title = action.user.name
@@ -317,7 +250,6 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
// Only update if this is a new favorite.
if (!state.favorites.has(favorite.id)) {
state.favorites.add(favorite.id)
- updateMaxId(favorite)
favoriteStatus(favorite)
}
},
@@ -330,7 +262,6 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
},
'deletion': (deletion) => {
const uri = deletion.uri
- updateMaxId(deletion)
// Remove possible notification
const status = find(allStatuses, {uri})
@@ -361,6 +292,9 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
// Keep the visible statuses sorted
if (timeline) {
sortTimeline(timelineObject)
+ if ((older || timelineObject.minVisibleId <= 0) && statuses.length > 0) {
+ timelineObject.minVisibleId = minBy(statuses, 'id').id
+ }
}
}
@@ -371,27 +305,12 @@ export const mutations = {
oldTimeline.newStatusCount = 0
oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50)
+ oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id
oldTimeline.visibleStatusesObject = {}
each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status })
},
clearTimeline (state, { timeline }) {
- const emptyTimeline = {
- statuses: [],
- statusesObject: {},
- faves: [],
- visibleStatuses: [],
- visibleStatusesObject: {},
- newStatusCount: 0,
- maxId: 0,
- minVisibleId: 0,
- loading: false,
- followers: [],
- friends: [],
- viewing: 'statuses',
- flushMarker: 0
- }
-
- state.timelines[timeline] = emptyTimeline
+ state.timelines[timeline] = emptyTl()
},
setFavorited (state, { status, value }) {
const newStatus = state.allStatusesObject[status.id]
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
index 6863bd0a..9dc4a3e1 100644
--- a/src/services/style_setter/style_setter.js
+++ b/src/services/style_setter/style_setter.js
@@ -45,12 +45,8 @@ const setStyle = (href, commit) => {
const styleEl = document.createElement('style')
head.appendChild(styleEl)
- const styleSheet = styleEl.sheet
+ // const styleSheet = styleEl.sheet
- styleSheet.insertRule(`a { color: ${colors['base08']}`, 'index-max')
- styleSheet.insertRule(`body { color: ${colors['base05']}`, 'index-max')
- styleSheet.insertRule(`.base05-border { border-color: ${colors['base05']}`, 'index-max')
- styleSheet.insertRule(`.base03-border { border-color: ${colors['base03']}`, 'index-max')
body.style.display = 'initial'
}
@@ -68,37 +64,47 @@ const setColors = (col, commit) => {
const isDark = (col.text.r + col.text.g + col.text.b) > (col.bg.r + col.bg.g + col.bg.b)
let colors = {}
+ let radii = {}
- let mod = 10
- if (isDark) {
- mod = mod * -1
- }
+ const mod = isDark ? -10 : 10
+
+ colors.bg = rgb2hex(col.bg.r, col.bg.g, col.bg.b) // background
+ colors.lightBg = rgb2hex((col.bg.r + col.fg.r) / 2, (col.bg.g + col.fg.g) / 2, (col.bg.b + col.fg.b) / 2) // hilighted bg
+ colors.btn = rgb2hex(col.fg.r, col.fg.g, col.fg.b) // panels & buttons
+ colors.border = rgb2hex(col.fg.r - mod, col.fg.g - mod, col.fg.b - mod) // borders
+ colors.faint = rgb2hex(
+ col.text.r * 0.45 + col.fg.r * 0.55,
+ col.text.g * 0.45 + col.fg.g * 0.55,
+ col.text.b * 0.45 + col.fg.b * 0.55) // faint text
+ colors.fg = rgb2hex(col.text.r, col.text.g, col.text.b) // text
+ colors.lightFg = rgb2hex(col.text.r - mod, col.text.g - mod, col.text.b - mod) // strong text
- colors['base00'] = rgb2hex(col.bg.r, col.bg.g, col.bg.b) // background
- colors['base01'] = rgb2hex((col.bg.r + col.fg.r) / 2, (col.bg.g + col.fg.g) / 2, (col.bg.b + col.fg.b) / 2) // hilighted bg
- colors['base02'] = rgb2hex(col.fg.r, col.fg.g, col.fg.b) // panels & buttons
- colors['base03'] = rgb2hex(col.fg.r - mod, col.fg.g - mod, col.fg.b - mod) // borders
- colors['base04'] = rgb2hex(col.text.r + mod * 2, col.text.g + mod * 2, col.text.b + mod * 2) // faint text
- colors['base05'] = rgb2hex(col.text.r, col.text.g, col.text.b) // text
- colors['base06'] = rgb2hex(col.text.r - mod, col.text.g - mod, col.text.b - mod) // strong text
colors['base07'] = rgb2hex(col.text.r - mod * 2, col.text.g - mod * 2, col.text.b - mod * 2)
- colors['base08'] = rgb2hex(col.link.r, col.link.g, col.link.b) // links
- colors['base09'] = rgb2hex((col.bg.r + col.text.r) / 2, (col.bg.g + col.text.g) / 2, (col.bg.b + col.text.b) / 2) // icons
-
- const num = 10
- times(num, (n) => {
- const color = colors[`base0${num - 1 - n}`]
- styleSheet.insertRule(`.base0${num - 1 - n} { color: ${color}`, 'index-max')
- styleSheet.insertRule(`.base0${num - 1 - n}-background { background-color: ${color}`, 'index-max')
- })
-
- styleSheet.insertRule(`a { color: ${colors['base08']}`, 'index-max')
- styleSheet.insertRule(`body { color: ${colors['base05']}`, 'index-max')
- styleSheet.insertRule(`.base05-border { border-color: ${colors['base05']}`, 'index-max')
- styleSheet.insertRule(`.base03-border { border-color: ${colors['base03']}`, 'index-max')
+
+ colors.link = rgb2hex(col.link.r, col.link.g, col.link.b) // links
+ colors.icon = rgb2hex((col.bg.r + col.text.r) / 2, (col.bg.g + col.text.g) / 2, (col.bg.b + col.text.b) / 2) // icons
+
+ colors.cBlue = col.cBlue && rgb2hex(col.cBlue.r, col.cBlue.g, col.cBlue.b)
+ colors.cRed = col.cRed && rgb2hex(col.cRed.r, col.cRed.g, col.cRed.b)
+ colors.cGreen = col.cGreen && rgb2hex(col.cGreen.r, col.cGreen.g, col.cGreen.b)
+ colors.cOrange = col.cOrange && rgb2hex(col.cOrange.r, col.cOrange.g, col.cOrange.b)
+
+ colors.cAlertRed = col.cRed && `rgba(${col.cRed.r}, ${col.cRed.g}, ${col.cRed.b}, .5)`
+
+ radii.btnRadius = col.btnRadius
+ radii.panelRadius = col.panelRadius
+ radii.avatarRadius = col.avatarRadius
+ radii.avatarAltRadius = col.avatarAltRadius
+ radii.tooltipRadius = col.tooltipRadius
+ radii.attachmentRadius = col.attachmentRadius
+
+ styleSheet.toString()
+ styleSheet.insertRule(`body { ${Object.entries(colors).filter(([k, v]) => v).map(([k, v]) => `--${k}: ${v}`).join(';')} }`, 'index-max')
+ styleSheet.insertRule(`body { ${Object.entries(radii).filter(([k, v]) => v).map(([k, v]) => `--${k}: ${v}px`).join(';')} }`, 'index-max')
body.style.display = 'initial'
commit('setOption', { name: 'colors', value: colors })
+ commit('setOption', { name: 'radii', value: radii })
commit('setOption', { name: 'customTheme', value: col })
}
@@ -111,12 +117,23 @@ const setPreset = (val, commit) => {
const fgRgb = hex2rgb(theme[2])
const textRgb = hex2rgb(theme[3])
const linkRgb = hex2rgb(theme[4])
+
+ const cRedRgb = hex2rgb(theme[5] || '#FF0000')
+ const cGreenRgb = hex2rgb(theme[6] || '#00FF00')
+ const cBlueRgb = hex2rgb(theme[7] || '#0000FF')
+ const cOrangeRgb = hex2rgb(theme[8] || '#E3FF00')
+
const col = {
bg: bgRgb,
fg: fgRgb,
text: textRgb,
- link: linkRgb
+ link: linkRgb,
+ cRed: cRedRgb,
+ cBlue: cBlueRgb,
+ cGreen: cGreenRgb,
+ cOrange: cOrangeRgb
}
+
// This is a hack, this function is only called during initial load.
// We want to cancel loading the theme from config.json if we're already
// loading a theme from the persisted state.
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index a4a80df0..bb5fdc2e 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -30,7 +30,7 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
return apiService.fetchTimeline(args)
.then((statuses) => {
- if (!older && statuses.length >= 20) {
+ if (!older && statuses.length >= 20 && !timelineData.loading) {
store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
}
update({store, statuses, timeline, showImmediately})
diff --git a/static/aurora_borealis.jpg b/static/aurora_borealis.jpg
new file mode 100644
index 00000000..b6a0daf9
--- /dev/null
+++ b/static/aurora_borealis.jpg
Binary files differ
diff --git a/static/bg.jpg b/static/bg2.jpg
index 60e2311a..60e2311a 100644
--- a/static/bg.jpg
+++ b/static/bg2.jpg
Binary files differ
diff --git a/static/config.json b/static/config.json
index 23fdf8a8..fc1b0795 100644
--- a/static/config.json
+++ b/static/config.json
@@ -1,6 +1,6 @@
{
"theme": "pleroma-dark",
- "background": "/static/bg.jpg",
+ "background": "/static/aurora_borealis.jpg",
"logo": "/static/logo.png",
"defaultPath": "/main/all",
"chatDisabled": false,
diff --git a/static/font/config.json b/static/font/config.json
index 98ece6ad..37adff79 100644
--- a/static/font/config.json
+++ b/static/font/config.json
@@ -95,6 +95,66 @@
"css": "logout",
"code": 59400,
"src": "fontawesome"
+ },
+ {
+ "uid": "ccddff8e8670dcd130e3cb55fdfc2fd0",
+ "css": "down-open",
+ "code": 59401,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "44b9e75612c5fad5505edd70d071651f",
+ "css": "attach",
+ "code": 59402,
+ "src": "entypo"
+ },
+ {
+ "uid": "e15f0d620a7897e2035c18c80142f6d9",
+ "css": "link-ext",
+ "code": 61582,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "381da2c2f7fd51f8de877c044d7f439d",
+ "css": "picture",
+ "code": 59403,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "872d9516df93eb6b776cc4d94bd97dac",
+ "css": "video",
+ "code": 59404,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "399ef63b1e23ab1b761dfbb5591fa4da",
+ "css": "right-open",
+ "code": 59405,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "d870630ff8f81e6de3958ecaeac532f2",
+ "css": "left-open",
+ "code": 59406,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "fe6697b391355dec12f3d86d6d490397",
+ "css": "up-open",
+ "code": 59407,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "9c1376672bb4f1ed616fdd78a23667e9",
+ "css": "comment-empty",
+ "code": 61669,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "cd21cbfb28ad4d903cede582157f65dc",
+ "css": "bell",
+ "code": 59408,
+ "src": "fontawesome"
}
]
} \ No newline at end of file
diff --git a/static/font/css/animation.css b/static/font/css/animation.css
index c8cfc252..ac5a9562 100644
--- a/static/font/css/animation.css
+++ b/static/font/css/animation.css
@@ -8,13 +8,6 @@
animation: spin 2s infinite linear;
display: inline-block;
}
-.animate-spin-slow {
- -moz-animation: spin 4s infinite linear;
- -o-animation: spin 4s infinite linear;
- -webkit-animation: spin 4s infinite linear;
- animation: spin 4s infinite linear;
- display: inline-block;
-}
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
diff --git a/static/font/css/fontello-codes.css b/static/font/css/fontello-codes.css
index 8831e4ee..e4e4e64d 100644
--- a/static/font/css/fontello-codes.css
+++ b/static/font/css/fontello-codes.css
@@ -8,9 +8,19 @@
.icon-plus-squared:before { content: '\e806'; } /* '' */
.icon-cog:before { content: '\e807'; } /* '' */
.icon-logout:before { content: '\e808'; } /* '' */
+.icon-down-open:before { content: '\e809'; } /* '' */
+.icon-attach:before { content: '\e80a'; } /* '' */
+.icon-picture:before { content: '\e80b'; } /* '' */
+.icon-video:before { content: '\e80c'; } /* '' */
+.icon-right-open:before { content: '\e80d'; } /* '' */
+.icon-left-open:before { content: '\e80e'; } /* '' */
+.icon-up-open:before { content: '\e80f'; } /* '' */
+.icon-bell:before { content: '\e810'; } /* '' */
.icon-spin3:before { content: '\e832'; } /* '' */
.icon-spin4:before { content: '\e834'; } /* '' */
+.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */
+.icon-comment-empty:before { content: '\f0e5'; } /* '' */
.icon-reply:before { content: '\f112'; } /* '' */
.icon-binoculars:before { content: '\f1e5'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */ \ No newline at end of file
diff --git a/static/font/css/fontello-embedded.css b/static/font/css/fontello-embedded.css
index f9d38315..20e498fe 100644
--- a/static/font/css/fontello-embedded.css
+++ b/static/font/css/fontello-embedded.css
@@ -1,15 +1,15 @@
@font-face {
font-family: 'fontello';
- src: url('../font/fontello.eot?34768509');
- src: url('../font/fontello.eot?34768509#iefix') format('embedded-opentype'),
- url('../font/fontello.svg?34768509#fontello') format('svg');
+ src: url('../font/fontello.eot?12951540');
+ src: url('../font/fontello.eot?12951540#iefix') format('embedded-opentype'),
+ url('../font/fontello.svg?12951540#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'fontello';
- src: url('data:application/octet-stream;base64,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') format('woff'),
- url('data:application/octet-stream;base64,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') format('truetype');
+ src: url('data:application/octet-stream;base64,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') format('woff'),
+ url('data:application/octet-stream;base64,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') format('truetype');
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
@@ -17,7 +17,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
- src: url('../font/fontello.svg?34768509#fontello') format('svg');
+ src: url('../font/fontello.svg?12951540#fontello') format('svg');
}
}
*/
@@ -61,9 +61,19 @@
.icon-plus-squared:before { content: '\e806'; } /* '' */
.icon-cog:before { content: '\e807'; } /* '' */
.icon-logout:before { content: '\e808'; } /* '' */
+.icon-down-open:before { content: '\e809'; } /* '' */
+.icon-attach:before { content: '\e80a'; } /* '' */
+.icon-picture:before { content: '\e80b'; } /* '' */
+.icon-video:before { content: '\e80c'; } /* '' */
+.icon-right-open:before { content: '\e80d'; } /* '' */
+.icon-left-open:before { content: '\e80e'; } /* '' */
+.icon-up-open:before { content: '\e80f'; } /* '' */
+.icon-bell:before { content: '\e810'; } /* '' */
.icon-spin3:before { content: '\e832'; } /* '' */
.icon-spin4:before { content: '\e834'; } /* '' */
+.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */
+.icon-comment-empty:before { content: '\f0e5'; } /* '' */
.icon-reply:before { content: '\f112'; } /* '' */
.icon-binoculars:before { content: '\f1e5'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */ \ No newline at end of file
diff --git a/static/font/css/fontello-ie7-codes.css b/static/font/css/fontello-ie7-codes.css
index 3c915b3c..d7a5a523 100644
--- a/static/font/css/fontello-ie7-codes.css
+++ b/static/font/css/fontello-ie7-codes.css
@@ -8,9 +8,19 @@
.icon-plus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
.icon-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }
+.icon-down-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe809;&nbsp;'); }
+.icon-attach { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80a;&nbsp;'); }
+.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80b;&nbsp;'); }
+.icon-video { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80c;&nbsp;'); }
+.icon-right-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80d;&nbsp;'); }
+.icon-left-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80e;&nbsp;'); }
+.icon-up-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80f;&nbsp;'); }
+.icon-bell { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe810;&nbsp;'); }
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe832;&nbsp;'); }
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe834;&nbsp;'); }
+.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;&nbsp;'); }
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;&nbsp;'); }
+.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;&nbsp;'); }
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;&nbsp;'); }
.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf1e5;&nbsp;'); }
.icon-user-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf234;&nbsp;'); } \ No newline at end of file
diff --git a/static/font/css/fontello-ie7.css b/static/font/css/fontello-ie7.css
index 2fe2a707..5ca12cea 100644
--- a/static/font/css/fontello-ie7.css
+++ b/static/font/css/fontello-ie7.css
@@ -19,9 +19,19 @@
.icon-plus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
.icon-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }
+.icon-down-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe809;&nbsp;'); }
+.icon-attach { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80a;&nbsp;'); }
+.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80b;&nbsp;'); }
+.icon-video { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80c;&nbsp;'); }
+.icon-right-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80d;&nbsp;'); }
+.icon-left-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80e;&nbsp;'); }
+.icon-up-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80f;&nbsp;'); }
+.icon-bell { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe810;&nbsp;'); }
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe832;&nbsp;'); }
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe834;&nbsp;'); }
+.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;&nbsp;'); }
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;&nbsp;'); }
+.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;&nbsp;'); }
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;&nbsp;'); }
.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf1e5;&nbsp;'); }
.icon-user-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf234;&nbsp;'); } \ No newline at end of file
diff --git a/static/font/css/fontello.css b/static/font/css/fontello.css
index 0c0d2930..5cc6f97d 100644
--- a/static/font/css/fontello.css
+++ b/static/font/css/fontello.css
@@ -1,11 +1,11 @@
@font-face {
font-family: 'fontello';
- src: url('../font/fontello.eot?64848116');
- src: url('../font/fontello.eot?64848116#iefix') format('embedded-opentype'),
- url('../font/fontello.woff2?64848116') format('woff2'),
- url('../font/fontello.woff?64848116') format('woff'),
- url('../font/fontello.ttf?64848116') format('truetype'),
- url('../font/fontello.svg?64848116#fontello') format('svg');
+ src: url('../font/fontello.eot?47566415');
+ src: url('../font/fontello.eot?47566415#iefix') format('embedded-opentype'),
+ url('../font/fontello.woff2?47566415') format('woff2'),
+ url('../font/fontello.woff?47566415') format('woff'),
+ url('../font/fontello.ttf?47566415') format('truetype'),
+ url('../font/fontello.svg?47566415#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -15,7 +15,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
- src: url('../font/fontello.svg?64848116#fontello') format('svg');
+ src: url('../font/fontello.svg?47566415#fontello') format('svg');
}
}
*/
@@ -64,9 +64,19 @@
.icon-plus-squared:before { content: '\e806'; } /* '' */
.icon-cog:before { content: '\e807'; } /* '' */
.icon-logout:before { content: '\e808'; } /* '' */
+.icon-down-open:before { content: '\e809'; } /* '' */
+.icon-attach:before { content: '\e80a'; } /* '' */
+.icon-picture:before { content: '\e80b'; } /* '' */
+.icon-video:before { content: '\e80c'; } /* '' */
+.icon-right-open:before { content: '\e80d'; } /* '' */
+.icon-left-open:before { content: '\e80e'; } /* '' */
+.icon-up-open:before { content: '\e80f'; } /* '' */
+.icon-bell:before { content: '\e810'; } /* '' */
.icon-spin3:before { content: '\e832'; } /* '' */
.icon-spin4:before { content: '\e834'; } /* '' */
+.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */
+.icon-comment-empty:before { content: '\f0e5'; } /* '' */
.icon-reply:before { content: '\f112'; } /* '' */
.icon-binoculars:before { content: '\f1e5'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */ \ No newline at end of file
diff --git a/static/font/demo.html b/static/font/demo.html
index 2c5503c0..d01bd1d6 100644
--- a/static/font/demo.html
+++ b/static/font/demo.html
@@ -229,11 +229,11 @@ body {
}
@font-face {
font-family: 'fontello';
- src: url('./font/fontello.eot?1253892');
- src: url('./font/fontello.eot?1253892#iefix') format('embedded-opentype'),
- url('./font/fontello.woff?1253892') format('woff'),
- url('./font/fontello.ttf?1253892') format('truetype'),
- url('./font/fontello.svg?1253892#fontello') format('svg');
+ src: url('./font/fontello.eot?34497073');
+ src: url('./font/fontello.eot?34497073#iefix') format('embedded-opentype'),
+ url('./font/fontello.woff?34497073') format('woff'),
+ url('./font/fontello.ttf?34497073') format('truetype'),
+ url('./font/fontello.svg?34497073#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -275,7 +275,7 @@ body {
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
</style>
- <link rel="stylesheet" href="css/animation.css"><!--[if IE 7]><link rel="stylesheet" href="css/fontello-ie7.css"><![endif]-->
+ <link rel="stylesheet" href="css/animation.css"><!--[if IE 7]><link rel="stylesheet" href="css/" + font.fontname + "-ie7.css"><![endif]-->
<script>
function toggleCodes(on) {
var obj = document.getElementById('icons');
@@ -291,37 +291,50 @@ body {
</head>
<body>
<div class="container header">
- <h1>
- fontello
- <small>font demo</small>
- </h1>
+ <h1>fontello <small>font demo</small></h1>
<label class="switch">
<input type="checkbox" onclick="toggleCodes(this.checked)">show codes
</label>
</div>
- <div id="icons" class="container">
+ <div class="container" id="icons">
<div class="row">
- <div title="Code: 0xe800" class="the-icons span3"><i class="demo-icon icon-cancel">&#xe800;</i> <span class="i-name">icon-cancel</span><span class="i-code">0xe800</span></div>
- <div title="Code: 0xe801" class="the-icons span3"><i class="demo-icon icon-upload">&#xe801;</i> <span class="i-name">icon-upload</span><span class="i-code">0xe801</span></div>
- <div title="Code: 0xe802" class="the-icons span3"><i class="demo-icon icon-star">&#xe802;</i> <span class="i-name">icon-star</span><span class="i-code">0xe802</span></div>
- <div title="Code: 0xe803" class="the-icons span3"><i class="demo-icon icon-star-empty">&#xe803;</i> <span class="i-name">icon-star-empty</span><span class="i-code">0xe803</span></div>
+ <div class="the-icons span3" title="Code: 0xe800"><i class="demo-icon icon-cancel">&#xe800;</i> <span class="i-name">icon-cancel</span><span class="i-code">0xe800</span></div>
+ <div class="the-icons span3" title="Code: 0xe801"><i class="demo-icon icon-upload">&#xe801;</i> <span class="i-name">icon-upload</span><span class="i-code">0xe801</span></div>
+ <div class="the-icons span3" title="Code: 0xe802"><i class="demo-icon icon-star">&#xe802;</i> <span class="i-name">icon-star</span><span class="i-code">0xe802</span></div>
+ <div class="the-icons span3" title="Code: 0xe803"><i class="demo-icon icon-star-empty">&#xe803;</i> <span class="i-name">icon-star-empty</span><span class="i-code">0xe803</span></div>
</div>
<div class="row">
- <div title="Code: 0xe804" class="the-icons span3"><i class="demo-icon icon-retweet">&#xe804;</i> <span class="i-name">icon-retweet</span><span class="i-code">0xe804</span></div>
- <div title="Code: 0xe805" class="the-icons span3"><i class="demo-icon icon-eye-off">&#xe805;</i> <span class="i-name">icon-eye-off</span><span class="i-code">0xe805</span></div>
- <div title="Code: 0xe806" class="the-icons span3"><i class="demo-icon icon-plus-squared">&#xe806;</i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xe806</span></div>
- <div title="Code: 0xe807" class="the-icons span3"><i class="demo-icon icon-cog">&#xe807;</i> <span class="i-name">icon-cog</span><span class="i-code">0xe807</span></div>
+ <div class="the-icons span3" title="Code: 0xe804"><i class="demo-icon icon-retweet">&#xe804;</i> <span class="i-name">icon-retweet</span><span class="i-code">0xe804</span></div>
+ <div class="the-icons span3" title="Code: 0xe805"><i class="demo-icon icon-eye-off">&#xe805;</i> <span class="i-name">icon-eye-off</span><span class="i-code">0xe805</span></div>
+ <div class="the-icons span3" title="Code: 0xe806"><i class="demo-icon icon-plus-squared">&#xe806;</i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xe806</span></div>
+ <div class="the-icons span3" title="Code: 0xe807"><i class="demo-icon icon-cog">&#xe807;</i> <span class="i-name">icon-cog</span><span class="i-code">0xe807</span></div>
</div>
<div class="row">
- <div title="Code: 0xe808" class="the-icons span3"><i class="demo-icon icon-logout">&#xe808;</i> <span class="i-name">icon-logout</span><span class="i-code">0xe808</span></div>
- <div title="Code: 0xe832" class="the-icons span3"><i class="demo-icon icon-spin3 animate-spin">&#xe832;</i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
- <div title="Code: 0xe834" class="the-icons span3"><i class="demo-icon icon-spin4 animate-spin">&#xe834;</i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
- <div title="Code: 0xf0c9" class="the-icons span3"><i class="demo-icon icon-menu">&#xf0c9;</i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
+ <div class="the-icons span3" title="Code: 0xe808"><i class="demo-icon icon-logout">&#xe808;</i> <span class="i-name">icon-logout</span><span class="i-code">0xe808</span></div>
+ <div class="the-icons span3" title="Code: 0xe809"><i class="demo-icon icon-down-open">&#xe809;</i> <span class="i-name">icon-down-open</span><span class="i-code">0xe809</span></div>
+ <div class="the-icons span3" title="Code: 0xe80a"><i class="demo-icon icon-attach">&#xe80a;</i> <span class="i-name">icon-attach</span><span class="i-code">0xe80a</span></div>
+ <div class="the-icons span3" title="Code: 0xe80b"><i class="demo-icon icon-picture">&#xe80b;</i> <span class="i-name">icon-picture</span><span class="i-code">0xe80b</span></div>
</div>
<div class="row">
- <div title="Code: 0xf112" class="the-icons span3"><i class="demo-icon icon-reply">&#xf112;</i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
- <div title="Code: 0xf1e5" class="the-icons span3"><i class="demo-icon icon-binoculars">&#xf1e5;</i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
- <div title="Code: 0xf234" class="the-icons span3"><i class="demo-icon icon-user-plus">&#xf234;</i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div>
+ <div class="the-icons span3" title="Code: 0xe80c"><i class="demo-icon icon-video">&#xe80c;</i> <span class="i-name">icon-video</span><span class="i-code">0xe80c</span></div>
+ <div class="the-icons span3" title="Code: 0xe80d"><i class="demo-icon icon-right-open">&#xe80d;</i> <span class="i-name">icon-right-open</span><span class="i-code">0xe80d</span></div>
+ <div class="the-icons span3" title="Code: 0xe80e"><i class="demo-icon icon-left-open">&#xe80e;</i> <span class="i-name">icon-left-open</span><span class="i-code">0xe80e</span></div>
+ <div class="the-icons span3" title="Code: 0xe80f"><i class="demo-icon icon-up-open">&#xe80f;</i> <span class="i-name">icon-up-open</span><span class="i-code">0xe80f</span></div>
+ </div>
+ <div class="row">
+ <div class="the-icons span3" title="Code: 0xe810"><i class="demo-icon icon-bell">&#xe810;</i> <span class="i-name">icon-bell</span><span class="i-code">0xe810</span></div>
+ <div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin">&#xe832;</i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
+ <div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin">&#xe834;</i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
+ <div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext">&#xf08e;</i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
+ </div>
+ <div class="row">
+ <div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu">&#xf0c9;</i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
+ <div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty">&#xf0e5;</i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
+ <div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply">&#xf112;</i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
+ <div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars">&#xf1e5;</i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
+ </div>
+ <div class="row">
+ <div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus">&#xf234;</i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div>
</div>
</div>
<div class="container footer">Generated by <a href="http://fontello.com">fontello.com</a></div>
diff --git a/static/font/font/fontello.eot b/static/font/font/fontello.eot
index 52fbefa9..d15e8391 100644
--- a/static/font/font/fontello.eot
+++ b/static/font/font/fontello.eot
Binary files differ
diff --git a/static/font/font/fontello.svg b/static/font/font/fontello.svg
index 43e9bee4..be07ddae 100644
--- a/static/font/font/fontello.svg
+++ b/static/font/font/fontello.svg
@@ -1,7 +1,7 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>Copyright (C) 2017 by original authors @ fontello.com</metadata>
+<metadata>Copyright (C) 2018 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
@@ -24,12 +24,32 @@
<glyph glyph-name="logout" unicode="&#xe808;" d="M357 46q0-2 1-11t0-14-2-14-5-11-12-3h-178q-67 0-114 47t-47 114v392q0 67 47 114t114 47h178q8 0 13-5t5-13q0-2 1-11t0-15-2-13-5-11-12-3h-178q-37 0-63-26t-27-64v-392q0-37 27-63t63-27h174t6 0 7-2 4-3 4-5 1-8z m518 304q0-14-11-25l-303-304q-11-10-25-10t-25 10-11 25v161h-250q-14 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 11 25t25 10 25-10l303-304q11-10 11-25z" horiz-adv-x="928.6" />
+<glyph glyph-name="down-open" unicode="&#xe809;" d="M939 399l-414-413q-10-11-25-11t-25 11l-414 413q-11 11-11 26t11 25l93 92q10 11 25 11t25-11l296-296 296 296q11 11 25 11t26-11l92-92q11-11 11-25t-11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="attach" unicode="&#xe80a;" d="M244-140q-102 0-170 72-72 70-74 166t84 190l496 496q80 80 174 54 44-12 79-47t47-79q26-96-54-176l-474-474q-40-40-88-46-48-4-80 28-30 24-27 74t47 92l332 334q24 26 50 0t0-50l-332-332q-44-44-20-70 12-8 24-6 24 4 46 26l474 474q50 50 34 108-16 60-76 76-54 14-108-36l-494-494q-66-76-64-143t52-117q50-48 117-50t141 62l496 494q24 24 50 0 26-22 0-48l-496-496q-82-82-186-82z" horiz-adv-x="939" />
+
+<glyph glyph-name="picture" unicode="&#xe80b;" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="video" unicode="&#xe80c;" d="M214-43v72q0 14-10 25t-25 10h-72q-14 0-25-10t-11-25v-72q0-14 11-25t25-11h72q14 0 25 11t10 25z m0 214v72q0 14-10 25t-25 11h-72q-14 0-25-11t-11-25v-72q0-14 11-25t25-10h72q14 0 25 10t10 25z m0 215v71q0 15-10 25t-25 11h-72q-14 0-25-11t-11-25v-71q0-15 11-25t25-11h72q14 0 25 11t10 25z m572-429v286q0 14-11 25t-25 11h-429q-14 0-25-11t-10-25v-286q0-14 10-25t25-11h429q15 0 25 11t11 25z m-572 643v71q0 15-10 26t-25 10h-72q-14 0-25-10t-11-26v-71q0-14 11-25t25-11h72q14 0 25 11t10 25z m786-643v72q0 14-11 25t-25 10h-71q-15 0-25-10t-11-25v-72q0-14 11-25t25-11h71q15 0 25 11t11 25z m-214 429v285q0 15-11 26t-25 10h-429q-14 0-25-10t-10-26v-285q0-15 10-25t25-11h429q15 0 25 11t11 25z m214-215v72q0 14-11 25t-25 11h-71q-15 0-25-11t-11-25v-72q0-14 11-25t25-10h71q15 0 25 10t11 25z m0 215v71q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-71q0-15 11-25t25-11h71q15 0 25 11t11 25z m0 214v71q0 15-11 26t-25 10h-71q-15 0-25-10t-11-26v-71q0-14 11-25t25-11h71q15 0 25 11t11 25z m71 89v-750q0-37-26-63t-63-26h-893q-36 0-63 26t-26 63v750q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="right-open" unicode="&#xe80d;" d="M618 361l-414-415q-11-10-25-10t-25 10l-93 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l93 93q10 11 25 11t25-11l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="left-open" unicode="&#xe80e;" d="M654 682l-297-296 297-297q10-10 10-25t-10-25l-93-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 11 25 11t25-11l93-93q10-10 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="up-open" unicode="&#xe80f;" d="M939 107l-92-92q-11-10-26-10t-25 10l-296 297-296-297q-11-10-25-10t-25 10l-93 92q-11 11-11 26t11 25l414 414q11 10 25 10t25-10l414-414q11-11 11-25t-11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bell" unicode="&#xe810;" d="M509-96q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m-372 160h726q-149 168-149 465 0 28-13 58t-39 58-67 45-95 17-95-17-67-45-39-58-13-58q0-297-149-465z m827 0q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
+
<glyph glyph-name="spin3" unicode="&#xe832;" d="M494 850c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
<glyph glyph-name="spin4" unicode="&#xe834;" d="M498 850c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
+<glyph glyph-name="link-ext" unicode="&#xf08e;" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
+
<glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
+<glyph glyph-name="comment-empty" unicode="&#xf0e5;" d="M500 636q-114 0-213-39t-157-105-59-142q0-62 40-119t113-98l48-28-15-53q-13-51-39-97 85 36 154 96l24 21 32-3q38-5 72-5 114 0 213 39t157 105 59 142-59 142-157 105-213 39z m500-286q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12h-3q-8 0-15 6t-9 15v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 97 67 179t182 130 251 48 251-48 182-130 67-179z" horiz-adv-x="1000" />
+
<glyph glyph-name="reply" unicode="&#xf112;" d="M1000 225q0-93-71-252-1-4-6-13t-7-17-7-12q-7-10-16-10-8 0-13 6t-5 14q0 5 1 15t2 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3h-125v-143q0-14-10-25t-26-11-25 11l-285 286q-11 10-11 25t11 25l285 286q11 10 25 10t26-10 10-25v-143h125q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
<glyph glyph-name="binoculars" unicode="&#xf1e5;" d="M393 671v-428q0-15-11-25t-25-11v-321q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v285l139 488q4 12 17 12h237z m178 0v-392h-142v392h142z m429-500v-285q0-15-11-25t-25-11h-285q-15 0-25 11t-11 25v321q-15 0-25 11t-11 25v428h237q13 0 17-12z m-589 661v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z m375 0v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z" horiz-adv-x="1000" />
diff --git a/static/font/font/fontello.ttf b/static/font/font/fontello.ttf
index 2548731d..3b08e96b 100644
--- a/static/font/font/fontello.ttf
+++ b/static/font/font/fontello.ttf
Binary files differ
diff --git a/static/font/font/fontello.woff b/static/font/font/fontello.woff
index fbbf748f..167d132d 100644
--- a/static/font/font/fontello.woff
+++ b/static/font/font/fontello.woff
Binary files differ
diff --git a/static/font/font/fontello.woff2 b/static/font/font/fontello.woff2
index 89c49787..224e9b97 100644
--- a/static/font/font/fontello.woff2
+++ b/static/font/font/fontello.woff2
Binary files differ
diff --git a/static/styles.json b/static/styles.json
index 92715565..7116ef20 100644
--- a/static/styles.json
+++ b/static/styles.json
@@ -1,9 +1,9 @@
{
- "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070" ],
- "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f" ],
- "classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c" ],
- "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8"],
- "ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60" ],
- "monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672" ],
- "mammal": [ "Mammal", "#272c37", "#444b5d", "#f8f8f8", "#9bacc8" ]
+ "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
+ "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
+ "classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
+ "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
+ "ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
+ "monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ],
+ "mammal": [ "Mammal", "#272c37", "#444b5d", "#f8f8f8", "#9bacc8", "#7f3142", "#2bd850", "#2b90d9", "#ca8f04" ]
}