forked from AkkomaGang/akkoma-fe
Merge branch 'develop' of ssh.gitgud.io:lambadalambda/pleroma-fe into feature/hash-routed
This commit is contained in:
commit
c2db700544
17 changed files with 178 additions and 34 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> A Qvitter-style frontend for certain GS servers.
|
> A Qvitter-style frontend for certain GS servers.
|
||||||
|
|
||||||
![screenshot](http://i.imgur.com/3q30Zxt.jpg)
|
![screenshot](https://my.mixtape.moe/kjzioz.PNG)
|
||||||
|
|
||||||
# FOR ADMINS
|
# FOR ADMINS
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
39
src/App.scss
39
src/App.scss
|
@ -213,13 +213,20 @@ nav {
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
flex: 1;
|
flex-basis: 60%;
|
||||||
flex-basis: 65%;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
flex: 1;
|
flex: 0;
|
||||||
flex-basis: 35%;
|
flex-basis: 35%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-flexer {
|
||||||
|
flex: 1;
|
||||||
|
flex-basis: 345px;
|
||||||
|
width: 365px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-shown {
|
.mobile-shown {
|
||||||
|
@ -238,6 +245,30 @@ nav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 960px) {
|
||||||
|
.sidebar {
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: 100vh;
|
||||||
|
width: 350px;
|
||||||
|
position: fixed;
|
||||||
|
margin-top: -10px;
|
||||||
|
|
||||||
|
.sidebar-container {
|
||||||
|
height: 96vh;
|
||||||
|
width: 362px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-right: 20px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sidebar-flexer {
|
||||||
|
max-height: 96vh;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media all and (max-width: 959px) {
|
@media all and (max-width: 959px) {
|
||||||
.mobile-hidden {
|
.mobile-hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
12
src/App.vue
12
src/App.vue
|
@ -15,10 +15,14 @@
|
||||||
<button @click="activatePanel('sidebar')">Sidebar</button>
|
<button @click="activatePanel('sidebar')">Sidebar</button>
|
||||||
<button @click="activatePanel('timeline')">Timeline</button>
|
<button @click="activatePanel('timeline')">Timeline</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar' }">
|
<div class="sidebar-flexer" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar'}">
|
||||||
<user-panel></user-panel>
|
<div class="sidebar" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar' }">
|
||||||
<nav-panel></nav-panel>
|
<div class="sidebar-container">
|
||||||
<notifications v-if="currentUser"></notifications>
|
<user-panel></user-panel>
|
||||||
|
<nav-panel></nav-panel>
|
||||||
|
<notifications v-if="currentUser"></notifications>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main" :class="{ 'mobile-hidden': mobileActivePanel != 'timeline' }">
|
<div class="main" :class="{ 'mobile-hidden': mobileActivePanel != 'timeline' }">
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
|
|
|
@ -33,10 +33,10 @@
|
||||||
.attachments {
|
.attachments {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-right: -0.8em;
|
margin-right: -0.7em;
|
||||||
.attachment {
|
.attachment {
|
||||||
flex: 1 0 30%;
|
flex: 1 0 30%;
|
||||||
margin: 0.5em 0.8em 0.6em 0.0em;
|
margin: 0.5em 0.7em 0.6em 0.0em;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
|
|
||||||
&.html {
|
&.html {
|
||||||
|
|
|
@ -8,6 +8,11 @@ const sortAndFilterConversation = (conversation) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = {
|
const conversation = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
highlight: null
|
||||||
|
}
|
||||||
|
},
|
||||||
props: [
|
props: [
|
||||||
'statusoid',
|
'statusoid',
|
||||||
'collapsable'
|
'collapsable'
|
||||||
|
@ -54,6 +59,9 @@ const conversation = {
|
||||||
} else {
|
} else {
|
||||||
return (id === this.statusoid.id)
|
return (id === this.statusoid.id)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setHighlight (id) {
|
||||||
|
this.highlight = Number(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<status v-for="status in conversation" :key="status.id" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true'></status>
|
<status v-for="status in conversation" @goto="setHighlight" :key="status.id" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true' :highlight="highlight"></status>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.notifications {
|
.notifications {
|
||||||
|
// a bit of a hack to allow scrolling below notifications
|
||||||
|
padding-bottom: 15em;
|
||||||
|
|
||||||
.panel-heading {
|
.panel-heading {
|
||||||
// force the text to stay centered, while keeping
|
// force the text to stay centered, while keeping
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
<div class='text'>
|
<div class='text'>
|
||||||
<timeago :since="notification.action.created_at" :auto-update="240"></timeago>
|
<timeago :since="notification.action.created_at" :auto-update="240"></timeago>
|
||||||
<div v-if="notification.type === 'favorite'">
|
<div v-if="notification.type === 'favorite'">
|
||||||
<h1>{{ notification.action.user.name }}<br><i class="fa icon-star"></i> favorited your <router-link :to="{ name: 'conversation', params: { id: notification.status.id } }">status</h1>
|
<h1>{{ notification.action.user.name }}<br><i class="fa icon-star"></i> favorited your <router-link :to="{ name: 'conversation', params: { id: notification.status.id } }">status</router-link></h1>
|
||||||
<p>{{ notification.status.text }}</p>
|
<p>{{ notification.status.text }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="notification.type === 'repeat'">
|
<div v-if="notification.type === 'repeat'">
|
||||||
<h1>{{ notification.action.user.name }}<br><i class="fa icon-retweet"></i> repeated your <router-link :to="{ name: 'conversation', params: { id: notification.status.id } }">status</h1>
|
<h1>{{ notification.action.user.name }}<br><i class="fa icon-retweet"></i> repeated your <router-link :to="{ name: 'conversation', params: { id: notification.status.id } }">status</router-link></h1>
|
||||||
<p>{{ notification.status.text }}</p>
|
<p>{{ notification.status.text }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="notification.type === 'mention'">
|
<div v-if="notification.type === 'mention'">
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
<div class="form-group" >
|
<div class="form-group" >
|
||||||
<textarea v-model="newStatus.status" placeholder="Just landed in L.A." rows="3" class="form-control" @keyup.meta.enter="postStatus(newStatus)" @keyup.ctrl.enter="postStatus(newStatus)" @drop="fileDrop" @dragover.prevent="fileDrag"></textarea>
|
<textarea v-model="newStatus.status" placeholder="Just landed in L.A." rows="3" class="form-control" @keyup.meta.enter="postStatus(newStatus)" @keyup.ctrl.enter="postStatus(newStatus)" @drop="fileDrop" @dragover.prevent="fileDrag"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='form-bottom'>
|
||||||
|
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
|
||||||
|
<button :disabled="submitDisabled" type="submit" class="btn btn-default base05 base01-background">Submit</button>
|
||||||
|
</div>
|
||||||
<div class="attachments">
|
<div class="attachments">
|
||||||
<div class="attachment" v-for="file in newStatus.files">
|
<div class="attachment" v-for="file in newStatus.files">
|
||||||
<i class="fa icon-cancel" @click="removeMediaFile(file)"></i>
|
<i class="fa icon-cancel" @click="removeMediaFile(file)"></i>
|
||||||
|
@ -13,10 +17,6 @@
|
||||||
<a v-if="type(file) === 'unknown'" :href="file.image">{{file.url}}</a>
|
<a v-if="type(file) === 'unknown'" :href="file.image">{{file.url}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='form-bottom'>
|
|
||||||
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
|
|
||||||
<button :disabled="submitDisabled" type="submit" class="btn btn-default base05 base01-background">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -44,14 +44,20 @@
|
||||||
.form-bottom {
|
.form-bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
flex: 2;
|
width: 10em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachments {
|
.attachments {
|
||||||
padding: 0.5em;
|
padding: 0 0.5em;
|
||||||
|
|
||||||
|
.attachment {
|
||||||
|
position: relative;
|
||||||
|
margin: 0.5em 0.8em 0.2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -11,7 +11,8 @@ const Status = {
|
||||||
'statusoid',
|
'statusoid',
|
||||||
'expandable',
|
'expandable',
|
||||||
'inConversation',
|
'inConversation',
|
||||||
'focused'
|
'focused',
|
||||||
|
'highlight'
|
||||||
],
|
],
|
||||||
data: () => ({
|
data: () => ({
|
||||||
replying: false,
|
replying: false,
|
||||||
|
@ -53,6 +54,16 @@ const Status = {
|
||||||
return {
|
return {
|
||||||
borderBottomColor: this.$store.state.config.colors['base02']
|
borderBottomColor: this.$store.state.config.colors['base02']
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isFocused () {
|
||||||
|
// retweet or root of an expanded conversation
|
||||||
|
if (this.focused) {
|
||||||
|
return true
|
||||||
|
} else if (!this.inConversation) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// use conversation highlight only when in conversation
|
||||||
|
return this.status.id === this.highlight
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -75,6 +86,10 @@ const Status = {
|
||||||
toggleReplying () {
|
toggleReplying () {
|
||||||
this.replying = !this.replying
|
this.replying = !this.replying
|
||||||
},
|
},
|
||||||
|
gotoOriginal () {
|
||||||
|
// only handled by conversation, not status_or_conversation
|
||||||
|
this.$emit('goto', this.status.in_reply_to_status_id)
|
||||||
|
},
|
||||||
toggleExpanded () {
|
toggleExpanded () {
|
||||||
this.$emit('toggleExpanded')
|
this.$emit('toggleExpanded')
|
||||||
},
|
},
|
||||||
|
@ -84,6 +99,20 @@ const Status = {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
this.userExpanded = !this.userExpanded
|
this.userExpanded = !this.userExpanded
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'highlight': function (id) {
|
||||||
|
id = Number(id)
|
||||||
|
if (this.status.id === id) {
|
||||||
|
let rect = this.$el.getBoundingClientRect()
|
||||||
|
if (rect.top < 100) {
|
||||||
|
window.scrollBy(0, rect.top - 200)
|
||||||
|
} else if (rect.bottom > window.innerHeight - 100) {
|
||||||
|
// will be useful when scrolling down to replies or root posts is in
|
||||||
|
window.scrollBy(0, rect.bottom + 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="status-el base00-background base03-border" v-if="!status.deleted" v-bind:class="[{ 'base01-background': focused }, { 'status-conversation': inConversation }]" >
|
<div class="status-el base00-background base03-border" v-if="!status.deleted" v-bind:class="[{ 'base01-background': isFocused }, { 'status-conversation': inConversation }]" >
|
||||||
<template v-if="muted">
|
<template v-if="muted">
|
||||||
<div class="media status container muted">
|
<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><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
|
||||||
|
@ -35,12 +35,10 @@
|
||||||
{{status.in_reply_to_screen_name}}
|
{{status.in_reply_to_screen_name}}
|
||||||
</router-link>
|
</router-link>
|
||||||
</small>
|
</small>
|
||||||
<template v-if="isReply">
|
<template v-if="isReply && !expandable">
|
||||||
<small>
|
<small>
|
||||||
<router-link :to="{ name: 'conversation', params: { id: status.in_reply_to_status_id } }">
|
<a href="#" @click.prevent="gotoOriginal" ><i class="icon-reply"></i></a>
|
||||||
<i class="icon-reply"></i>
|
</small>
|
||||||
</router-link>
|
|
||||||
</small>
|
|
||||||
</template>
|
</template>
|
||||||
-
|
-
|
||||||
<small>
|
<small>
|
||||||
|
|
|
@ -79,9 +79,8 @@
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
dailyAvg () {
|
dailyAvg () {
|
||||||
return Math.round(
|
const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000))
|
||||||
this.user.statuses_count / ((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000))
|
return Math.round(this.user.statuses_count / days)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -117,7 +116,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-panel-body {
|
.profile-panel-body {
|
||||||
padding-top: 0em;
|
|
||||||
top: -0em;
|
top: -0em;
|
||||||
padding-top: 4em;
|
padding-top: 4em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Pleroma FE",
|
"name": "Pleroma FE",
|
||||||
"theme": "base16-ashes.css",
|
"theme": "base16-pleroma-dark.css",
|
||||||
"background": "/static/bg.jpg",
|
"background": "/static/bg.jpg",
|
||||||
"logo": "/static/logo.png"
|
"logo": "/static/logo.png"
|
||||||
}
|
}
|
||||||
|
|
33
static/css/base16-pleroma-dark.css
Normal file
33
static/css/base16-pleroma-dark.css
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
.base00-background { background-color: #161c20; }
|
||||||
|
.base01-background { background-color: #282e32; }
|
||||||
|
.base02-background { background-color: #343a3f; }
|
||||||
|
.base03-background { background-color: #4e5256; }
|
||||||
|
.base04-background { background-color: #ababab; }
|
||||||
|
.base05-background { background-color: #b9b9b9; }
|
||||||
|
.base06-background { background-color: #d0d0d0; }
|
||||||
|
.base07-background { background-color: #e7e7e7; }
|
||||||
|
.base08-background { background-color: #baaa9c; }
|
||||||
|
.base09-background { background-color: #999999; }
|
||||||
|
.base0A-background { background-color: #a0a0a0; }
|
||||||
|
.base0B-background { background-color: #8e8e8e; }
|
||||||
|
.base0C-background { background-color: #868686; }
|
||||||
|
.base0D-background { background-color: #686868; }
|
||||||
|
.base0E-background { background-color: #747474; }
|
||||||
|
.base0F-background { background-color: #5e5e5e; }
|
||||||
|
|
||||||
|
.base00 { color: #161c20; }
|
||||||
|
.base01 { color: #282e32; }
|
||||||
|
.base02 { color: #36393e; }
|
||||||
|
.base03 { color: #4e5256; }
|
||||||
|
.base04 { color: #ababab; }
|
||||||
|
.base05 { color: #b9b9b9; }
|
||||||
|
.base06 { color: #d0d0d0; }
|
||||||
|
.base07 { color: #e7e7e7; }
|
||||||
|
.base08 { color: #baaa9c; }
|
||||||
|
.base09 { color: #999999; }
|
||||||
|
.base0A { color: #a0a0a0; }
|
||||||
|
.base0B { color: #8e8e8e; }
|
||||||
|
.base0C { color: #868686; }
|
||||||
|
.base0D { color: #686868; }
|
||||||
|
.base0E { color: #747474; }
|
||||||
|
.base0F { color: #5e5e5e; }
|
33
static/css/base16-pleroma-light.css
Normal file
33
static/css/base16-pleroma-light.css
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
.base00-background { background-color: #f2f4f6; }
|
||||||
|
.base01-background { background-color: #dde2e6; }
|
||||||
|
.base02-background { background-color: #c0c6cb; }
|
||||||
|
.base03-background { background-color: #a4a4a4; }
|
||||||
|
.base04-background { background-color: #545454; }
|
||||||
|
.base05-background { background-color: #304055; }
|
||||||
|
.base06-background { background-color: #040404; }
|
||||||
|
.base07-background { background-color: #000000; }
|
||||||
|
.base08-background { background-color: #e92f2f; }
|
||||||
|
.base09-background { background-color: #e09448; }
|
||||||
|
.base0A-background { background-color: #dddd13; }
|
||||||
|
.base0B-background { background-color: #0ed839; }
|
||||||
|
.base0C-background { background-color: #23edda; }
|
||||||
|
.base0D-background { background-color: #3b48e3; }
|
||||||
|
.base0E-background { background-color: #f996e2; }
|
||||||
|
.base0F-background { background-color: #69542d; }
|
||||||
|
|
||||||
|
.base00 { color: #f2f4f6; }
|
||||||
|
.base01 { color: #dde2e6; }
|
||||||
|
.base02 { color: #c0c6cb; }
|
||||||
|
.base03 { color: #a4a4a4; }
|
||||||
|
.base04 { color: #545454; }
|
||||||
|
.base05 { color: #304055; }
|
||||||
|
.base06 { color: #040404; }
|
||||||
|
.base07 { color: #000000; }
|
||||||
|
.base08 { color: #e46f0f; }
|
||||||
|
.base09 { color: #e09448; }
|
||||||
|
.base0A { color: #dddd13; }
|
||||||
|
.base0B { color: #0ed839; }
|
||||||
|
.base0C { color: #23edda; }
|
||||||
|
.base0D { color: #3b48e3; }
|
||||||
|
.base0E { color: #f996e2; }
|
||||||
|
.base0F { color: #69542d; }
|
|
@ -1,4 +1,6 @@
|
||||||
[
|
[
|
||||||
|
"base16-pleroma-dark.css",
|
||||||
|
"base16-pleroma-light.css",
|
||||||
"base16-3024.css",
|
"base16-3024.css",
|
||||||
"base16-apathy.css",
|
"base16-apathy.css",
|
||||||
"base16-ashes.css",
|
"base16-ashes.css",
|
||||||
|
|
Loading…
Reference in a new issue