Automatically rewrite to element-plus
This commit is contained in:
parent
2751da04b7
commit
0c427e8c34
|
@ -4,7 +4,13 @@
|
|||
<el-header>
|
||||
<el-row>
|
||||
<el-col :span="24" class="close">
|
||||
<el-button type="text" icon="el-icon-close" @click="close" class="close-button"> </el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
:icon="ElIconClose"
|
||||
@click="close"
|
||||
class="close-button"
|
||||
>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
|
@ -31,7 +37,12 @@
|
|||
<el-input></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="submit">
|
||||
<el-button type="primary" @click="authorizeSubmit" v-loading="submitting" element-loading-background="rgba(0, 0, 0, 0.8)">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="authorizeSubmit"
|
||||
v-loading="submitting"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
>
|
||||
{{ $t('authorize.submit') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
@ -42,25 +53,27 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Close as ElIconClose } from '@element-plus/icons'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
authorizeForm: {
|
||||
code: null,
|
||||
},
|
||||
submitting: false,
|
||||
ElIconClose,
|
||||
}
|
||||
},
|
||||
name: 'authorize',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
sns: {
|
||||
type: String,
|
||||
default: 'mastodon'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
authorizeForm: {
|
||||
code: null
|
||||
},
|
||||
submitting: false
|
||||
}
|
||||
default: 'mastodon',
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.url)
|
||||
|
@ -71,32 +84,32 @@ export default {
|
|||
this.$store
|
||||
.dispatch('Authorize/submit', {
|
||||
code: this.authorizeForm.code,
|
||||
sns: this.sns
|
||||
sns: this.sns,
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitting = false
|
||||
})
|
||||
.then(id => {
|
||||
.then((id) => {
|
||||
this.$router.push({ path: `/${id}/home` })
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
if (err.name === 'DuplicateRecordError') {
|
||||
this.$message({
|
||||
message: this.$t('message.authorize_duplicate_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.authorize_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
close() {
|
||||
return this.$router.push({ path: '/', query: { redirect: 'home' } })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -18,13 +18,26 @@
|
|||
v-bind:key="account._id"
|
||||
role="menuitem"
|
||||
>
|
||||
<i v-if="account.avatar === undefined || account.avatar === null || account.avatar === ''" class="el-icon-menu"></i>
|
||||
<FailoverImg v-else :src="account.avatar" class="avatar" :title="account.username + '@' + account.domain" />
|
||||
<FailoverImg :src="`${account.baseURL}/favicon.ico`" :failoverSrc="`${account.baseURL}/favicon.png`" class="instance-icon" />
|
||||
<el-icon><el-icon-menu /></el-icon>
|
||||
<FailoverImg
|
||||
v-else
|
||||
:src="account.avatar"
|
||||
class="avatar"
|
||||
:title="account.username + '@' + account.domain"
|
||||
/>
|
||||
<FailoverImg
|
||||
:src="`${account.baseURL}/favicon.ico`"
|
||||
:failoverSrc="`${account.baseURL}/favicon.png`"
|
||||
class="instance-icon"
|
||||
/>
|
||||
<span slot="title">{{ account.domain }}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/login" :title="$t('global_header.add_new_account')" role="menuitem">
|
||||
<i class="el-icon-plus"></i>
|
||||
<el-menu-item
|
||||
index="/login"
|
||||
:title="$t('global_header.add_new_account')"
|
||||
role="menuitem"
|
||||
>
|
||||
<el-icon><el-icon-plus /></el-icon>
|
||||
<span slot="new">New</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
|
@ -35,23 +48,26 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Menu as ElIconMenu, Plus as ElIconPlus } from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
|
||||
import { StreamingError } from '~/src/errors/streamingError'
|
||||
|
||||
export default {
|
||||
name: 'global-header',
|
||||
components: {
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
ElIconMenu,
|
||||
ElIconPlus,
|
||||
},
|
||||
name: 'global-header',
|
||||
computed: {
|
||||
...mapState('GlobalHeader', {
|
||||
accounts: state => state.accounts,
|
||||
hide: state => state.hide
|
||||
accounts: (state) => state.accounts,
|
||||
hide: (state) => state.hide,
|
||||
}),
|
||||
...mapState({
|
||||
themeColor: state => state.App.theme.global_header_color
|
||||
})
|
||||
themeColor: (state) => state.App.theme.global_header_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.initialize()
|
||||
|
@ -63,12 +79,14 @@ export default {
|
|||
async initialize() {
|
||||
await this.$store
|
||||
.dispatch('GlobalHeader/initLoad')
|
||||
.then(accounts => {
|
||||
this.$store.dispatch('GlobalHeader/startStreamings').catch(err => {
|
||||
.then((accounts) => {
|
||||
this.$store.dispatch('GlobalHeader/startStreamings').catch((err) => {
|
||||
if (err instanceof StreamingError) {
|
||||
this.$message({
|
||||
message: this.$t('message.start_all_streamings_error', { domain: err.domain }),
|
||||
type: 'error'
|
||||
message: this.$t('message.start_all_streamings_error', {
|
||||
domain: err.domain,
|
||||
}),
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -76,11 +94,11 @@ export default {
|
|||
this.$router.push({ path: `/${accounts[0]._id}/home` })
|
||||
}
|
||||
})
|
||||
.catch(_ => {
|
||||
.catch((_) => {
|
||||
return this.$router.push({ path: '/login' })
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,7 +3,13 @@
|
|||
<el-header>
|
||||
<el-row>
|
||||
<el-col :span="24" class="close">
|
||||
<el-button type="text" icon="el-icon-close" @click="close" class="close-button"> </el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
:icon="ElIconClose"
|
||||
@click="close"
|
||||
class="close-button"
|
||||
>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
|
@ -15,23 +21,29 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Close as ElIconClose } from '@element-plus/icons'
|
||||
import LoginForm from './Login/LoginForm'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
ElIconClose,
|
||||
}
|
||||
},
|
||||
name: 'login',
|
||||
components: { LoginForm },
|
||||
computed: {
|
||||
...mapState({
|
||||
page: state => state.Login.page
|
||||
})
|
||||
page: (state) => state.Login.page,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$store.dispatch('Login/pageBack')
|
||||
return this.$router.push({ path: '/', query: { redirect: 'home' } })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,10 +9,18 @@
|
|||
:model="form"
|
||||
>
|
||||
<el-form-item :label="$t('login.domain_name_label')" prop="domainName">
|
||||
<el-input v-model="form.domainName" placeholder="mastodon.social" v-shortkey="['enter']" @shortkey.native="handleKey"></el-input>
|
||||
<el-input
|
||||
v-model="form.domainName"
|
||||
placeholder="mastodon.social"
|
||||
v-shortkey="['enter']"
|
||||
@shortkey.native="handleKey"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<p class="proxy-info">
|
||||
{{ $t('login.proxy_info') }}<router-link to="/preferences/network">{{ $t('login.proxy_here') }}</router-link>
|
||||
{{ $t('login.proxy_info')
|
||||
}}<router-link to="/preferences/network">{{
|
||||
$t('login.proxy_here')
|
||||
}}</router-link>
|
||||
</p>
|
||||
<!-- Dummy form to guard submitting with enter -->
|
||||
<el-form-item class="hidden">
|
||||
|
@ -22,7 +30,13 @@
|
|||
<el-button type="primary" class="login" @click="login" v-if="allowLogin">
|
||||
{{ $t('login.login') }}
|
||||
</el-button>
|
||||
<el-button type="primary" v-else @click="confirm('loginForm')" v-loading="searching" element-loading-background="rgba(0, 0, 0, 0.8)">
|
||||
<el-button
|
||||
type="primary"
|
||||
v-else
|
||||
@click="confirm('loginForm')"
|
||||
v-loading="searching"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
>
|
||||
{{ $t('login.search') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
@ -38,18 +52,20 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
form: {
|
||||
domainName: ''
|
||||
}
|
||||
domainName: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
selectedInstance: state => state.Login.selectedInstance,
|
||||
searching: state => state.Login.searching,
|
||||
sns: state => state.Login.sns
|
||||
selectedInstance: (state) => state.Login.selectedInstance,
|
||||
searching: (state) => state.Login.searching,
|
||||
sns: (state) => state.Login.sns,
|
||||
}),
|
||||
allowLogin: function() {
|
||||
return this.selectedInstance && this.form.domainName === this.selectedInstance
|
||||
allowLogin: function () {
|
||||
return (
|
||||
this.selectedInstance && this.form.domainName === this.selectedInstance
|
||||
)
|
||||
},
|
||||
rules: {
|
||||
get() {
|
||||
|
@ -58,17 +74,17 @@ export default {
|
|||
{
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: this.$t('validation.login.require_domain_name')
|
||||
message: this.$t('validation.login.require_domain_name'),
|
||||
},
|
||||
{
|
||||
pattern: domainFormat,
|
||||
trigger: 'change',
|
||||
message: this.$t('validation.login.domain_format')
|
||||
}
|
||||
]
|
||||
message: this.$t('validation.login.domain_format'),
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
login() {
|
||||
|
@ -76,44 +92,51 @@ export default {
|
|||
lock: true,
|
||||
text: this.$t('message.loading'),
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
this.$store
|
||||
.dispatch('Login/fetchLogin')
|
||||
.then(url => {
|
||||
.then((url) => {
|
||||
loading.close()
|
||||
this.$store.dispatch('Login/pageBack')
|
||||
this.$router.push({ path: '/authorize', query: { url: url, sns: this.sns } })
|
||||
this.$router.push({
|
||||
path: '/authorize',
|
||||
query: { url: url, sns: this.sns },
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
loading.close()
|
||||
this.$message({
|
||||
message: this.$t('message.authorize_url_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
confirm(formName) {
|
||||
this.$refs[formName].validate(valid => {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$store
|
||||
.dispatch('Login/confirmInstance', this.form.domainName)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.domain_confirmed', { domain: this.form.domainName }),
|
||||
type: 'success'
|
||||
message: this.$t('message.domain_confirmed', {
|
||||
domain: this.form.domainName,
|
||||
}),
|
||||
type: 'success',
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.domain_doesnt_exist', { domain: this.form.domainName }),
|
||||
type: 'error'
|
||||
message: this.$t('message.domain_doesnt_exist', {
|
||||
domain: this.form.domainName,
|
||||
}),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('validation.login.domain_format'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
@ -125,8 +148,8 @@ export default {
|
|||
} else {
|
||||
this.login()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
<h1>{{ $t('preferences.title') }}</h1>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button type="text" icon="el-icon-close" @click="close" class="close-button" role="button"></el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
:icon="ElIconClose"
|
||||
@click="close"
|
||||
class="close-button"
|
||||
role="button"
|
||||
></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
|
@ -54,15 +60,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Close as ElIconClose } from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
ElIconClose,
|
||||
}
|
||||
},
|
||||
name: 'preferences',
|
||||
computed: {
|
||||
...mapState({
|
||||
primaryColor: state => state.App.theme.primary_color,
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
})
|
||||
primaryColor: (state) => state.App.theme.primary_color,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
|
@ -70,8 +82,8 @@ export default {
|
|||
},
|
||||
activeRoute() {
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -12,12 +12,25 @@
|
|||
v-loading="accountLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
>
|
||||
<el-table-column prop="username" :label="$t('preferences.account.username')"> </el-table-column>
|
||||
<el-table-column prop="domain" :label="$t('preferences.account.domain')"> </el-table-column>
|
||||
<el-table-column
|
||||
prop="username"
|
||||
:label="$t('preferences.account.username')"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="domain"
|
||||
:label="$t('preferences.account.domain')"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('preferences.account.association')">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click.native.prevent="removeAccount(scope.$index, accounts)" type="text" class="action">
|
||||
<i class="el-icon-close"></i> {{ $t('preferences.account.remove_association') }}
|
||||
<el-button
|
||||
@click.native.prevent="removeAccount(scope.$index, accounts)"
|
||||
type="text"
|
||||
class="action"
|
||||
>
|
||||
<el-icon><el-icon-close /></el-icon>
|
||||
{{ $t('preferences.account.remove_association') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -27,7 +40,7 @@
|
|||
<el-button
|
||||
class="arrow-up action"
|
||||
type="text"
|
||||
icon="el-icon-arrow-up"
|
||||
:icon="ElIconArrowUp"
|
||||
@click.native.prevent="forward(scope.$index, accounts)"
|
||||
></el-button>
|
||||
</div>
|
||||
|
@ -35,7 +48,7 @@
|
|||
<el-button
|
||||
class="arrow-down action"
|
||||
type="text"
|
||||
icon="el-icon-arrow-down"
|
||||
:icon="ElIconArrowDown"
|
||||
@click.native.prevent="backward(scope.$index, accounts)"
|
||||
></el-button>
|
||||
</div>
|
||||
|
@ -47,10 +60,22 @@
|
|||
<el-popover placement="top" width="160" v-model="deletePopoverVisible">
|
||||
<p>{{ $t('preferences.account.confirm_message') }}</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="deletePopoverVisible = false">{{ $t('preferences.account.cancel') }}</el-button>
|
||||
<el-button type="danger" size="mini" @click="removeAllAssociations">{{ $t('preferences.account.confirm') }}</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
@click="deletePopoverVisible = false"
|
||||
>{{ $t('preferences.account.cancel') }}</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="mini"
|
||||
@click="removeAllAssociations"
|
||||
>{{ $t('preferences.account.confirm') }}</el-button
|
||||
>
|
||||
</div>
|
||||
<el-button slot="reference" type="danger">{{ $t('preferences.account.remove_all_associations') }}</el-button>
|
||||
<el-button slot="reference" type="danger">{{
|
||||
$t('preferences.account.remove_all_associations')
|
||||
}}</el-button>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -58,24 +83,34 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
Close as ElIconClose,
|
||||
ArrowUp as ElIconArrowUp,
|
||||
ArrowDown as ElIconArrowDown,
|
||||
} from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'account',
|
||||
data() {
|
||||
return {
|
||||
openRemoveDialog: false,
|
||||
deletePopoverVisible: false
|
||||
deletePopoverVisible: false,
|
||||
ElIconArrowUp,
|
||||
ElIconArrowDown,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ElIconClose,
|
||||
},
|
||||
name: 'account',
|
||||
computed: {
|
||||
...mapState({
|
||||
accounts: state => state.Preferences.Account.accounts,
|
||||
accountLoading: state => state.Preferences.Account.accountLoading
|
||||
accounts: (state) => state.Preferences.Account.accounts,
|
||||
accountLoading: (state) => state.Preferences.Account.accountLoading,
|
||||
}),
|
||||
...mapState({
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
})
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.loadAccounts()
|
||||
|
@ -88,7 +123,7 @@ export default {
|
|||
} catch (err) {
|
||||
return this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('Preferences/Account/updateAccountLoading', false)
|
||||
|
@ -103,27 +138,31 @@ export default {
|
|||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.account_remove_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
forward(index, accounts) {
|
||||
this.$store.dispatch('Preferences/Account/forwardAccount', accounts[index]).then(() => {
|
||||
this.loadAccounts()
|
||||
})
|
||||
this.$store
|
||||
.dispatch('Preferences/Account/forwardAccount', accounts[index])
|
||||
.then(() => {
|
||||
this.loadAccounts()
|
||||
})
|
||||
},
|
||||
backward(index, accounts) {
|
||||
this.$store.dispatch('Preferences/Account/backwardAccount', accounts[index]).then(() => {
|
||||
this.loadAccounts()
|
||||
})
|
||||
this.$store
|
||||
.dispatch('Preferences/Account/backwardAccount', accounts[index])
|
||||
.then(() => {
|
||||
this.loadAccounts()
|
||||
})
|
||||
},
|
||||
removeAllAssociations() {
|
||||
this.deletePopoverVisible = false
|
||||
this.$store.dispatch('Preferences/Account/removeAllAccounts').then(() => {
|
||||
this.$router.push('/login')
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,45 +3,100 @@
|
|||
<h2>{{ $t('preferences.appearance.title') }}</h2>
|
||||
<el-form class="theme section" size="small" label-position="top">
|
||||
<div class="left">
|
||||
<el-form-item for="theme" :label="$t('preferences.appearance.theme_color')">
|
||||
<el-form-item
|
||||
for="theme"
|
||||
:label="$t('preferences.appearance.theme_color')"
|
||||
>
|
||||
<el-select id="theme" v-model="theme" placeholder="theme">
|
||||
<el-option v-for="t in themes" :key="t.key" :label="$t(t.name)" :value="t.key"> </el-option>
|
||||
<el-option
|
||||
v-for="t in themes"
|
||||
:key="t.key"
|
||||
:label="$t(t.name)"
|
||||
:value="t.key"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="right">
|
||||
<Toot :displayNameStyle="displayNameStyle" :timeFormat="timeFormat"></Toot>
|
||||
<Toot
|
||||
:displayNameStyle="displayNameStyle"
|
||||
:timeFormat="timeFormat"
|
||||
></Toot>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="color-pallet section" v-if="customizeThemeColor">
|
||||
<color-pallet></color-pallet>
|
||||
</div>
|
||||
<el-form class="font section" size="small" label-position="top">
|
||||
<el-form-item for="font-family" :label="$t('preferences.appearance.font_family')">
|
||||
<el-form-item
|
||||
for="font-family"
|
||||
:label="$t('preferences.appearance.font_family')"
|
||||
>
|
||||
<el-select id="font-family" v-model="font" placeholder="fonts">
|
||||
<el-option v-for="f in fontList" :key="f" :label="f" :value="f" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item for="font-size" :label="$t('preferences.appearance.font_size')">
|
||||
<el-input-number id="font-size" :value="fontSize" :min="9" :max="72" @change="updateFontSize"></el-input-number>
|
||||
<el-form-item
|
||||
for="font-size"
|
||||
:label="$t('preferences.appearance.font_size')"
|
||||
>
|
||||
<el-input-number
|
||||
id="font-size"
|
||||
:model-value="fontSize"
|
||||
:min="9"
|
||||
:max="72"
|
||||
@change="updateFontSize"
|
||||
></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="toot-padding section" size="small" label-position="top">
|
||||
<el-form-item for="toot-padding" :label="$t('preferences.appearance.toot_padding')">
|
||||
<el-input-number id="toot-padding" :value="tootPadding" :min="0" :max="24" @change="updateTootPadding"></el-input-number>
|
||||
<el-form-item
|
||||
for="toot-padding"
|
||||
:label="$t('preferences.appearance.toot_padding')"
|
||||
>
|
||||
<el-input-number
|
||||
id="toot-padding"
|
||||
:model-value="tootPadding"
|
||||
:min="0"
|
||||
:max="24"
|
||||
@change="updateTootPadding"
|
||||
></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="display-style section" size="small" label-position="top">
|
||||
<el-form-item for="display-style" :label="$t('preferences.appearance.display_style.title')">
|
||||
<el-select id="display-style" v-model="displayNameStyle" placeholder="style">
|
||||
<el-option v-for="style in nameStyles" :key="style.value" :label="$t(style.name)" :value="style.value"> </el-option>
|
||||
<el-form-item
|
||||
for="display-style"
|
||||
:label="$t('preferences.appearance.display_style.title')"
|
||||
>
|
||||
<el-select
|
||||
id="display-style"
|
||||
v-model="displayNameStyle"
|
||||
placeholder="style"
|
||||
>
|
||||
<el-option
|
||||
v-for="style in nameStyles"
|
||||
:key="style.value"
|
||||
:label="$t(style.name)"
|
||||
:value="style.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="time-format section" size="small" label-position="top">
|
||||
<el-form-item for="time-format" :label="$t('preferences.appearance.time_format.title')">
|
||||
<el-form-item
|
||||
for="time-format"
|
||||
:label="$t('preferences.appearance.time_format.title')"
|
||||
>
|
||||
<el-select id="time-format" v-model="timeFormat" placeholder="format">
|
||||
<el-option v-for="format in timeFormats" :key="format.value" :label="$t(format.name)" :value="format.value"> </el-option>
|
||||
<el-option
|
||||
v-for="format in timeFormats"
|
||||
:key="format.value"
|
||||
:label="$t(format.name)"
|
||||
:value="format.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -60,20 +115,32 @@ export default {
|
|||
name: 'appearance',
|
||||
components: {
|
||||
Toot,
|
||||
ColorPallet
|
||||
ColorPallet,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nameStyles: [DisplayStyle.DisplayNameAndUsername, DisplayStyle.DisplayName, DisplayStyle.Username],
|
||||
themes: [Theme.System, Theme.Light, Theme.Dark, Theme.SolarizedLight, Theme.SolarizedDark, Theme.KimbieDark, Theme.Custom],
|
||||
timeFormats: [TimeFormat.Absolute, TimeFormat.Relative]
|
||||
nameStyles: [
|
||||
DisplayStyle.DisplayNameAndUsername,
|
||||
DisplayStyle.DisplayName,
|
||||
DisplayStyle.Username,
|
||||
],
|
||||
themes: [
|
||||
Theme.System,
|
||||
Theme.Light,
|
||||
Theme.Dark,
|
||||
Theme.SolarizedLight,
|
||||
Theme.SolarizedDark,
|
||||
Theme.KimbieDark,
|
||||
Theme.Custom,
|
||||
],
|
||||
timeFormats: [TimeFormat.Absolute, TimeFormat.Relative],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('Preferences/Appearance', {
|
||||
fontSize: state => state.appearance.fontSize,
|
||||
fontList: state => state.fonts,
|
||||
tootPadding: state => state.appearance.tootPadding
|
||||
fontSize: (state) => state.appearance.fontSize,
|
||||
fontList: (state) => state.fonts,
|
||||
tootPadding: (state) => state.appearance.tootPadding,
|
||||
}),
|
||||
theme: {
|
||||
get() {
|
||||
|
@ -81,15 +148,19 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateTheme', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
displayNameStyle: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance.displayNameStyle
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.displayNameStyle
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateDisplayNameStyle', value)
|
||||
}
|
||||
this.$store.dispatch(
|
||||
'Preferences/Appearance/updateDisplayNameStyle',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
timeFormat: {
|
||||
get() {
|
||||
|
@ -97,7 +168,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateTimeFormat', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
customizeThemeColor() {
|
||||
return this.theme === Theme.Custom.key
|
||||
|
@ -108,8 +179,8 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateFont', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Preferences/Appearance/loadAppearance')
|
||||
|
@ -120,9 +191,12 @@ export default {
|
|||
await this.$store.dispatch('Preferences/Appearance/updateFontSize', value)
|
||||
},
|
||||
async updateTootPadding(value) {
|
||||
await this.$store.dispatch('Preferences/Appearance/updateTootPadding', value)
|
||||
}
|
||||
}
|
||||
await this.$store.dispatch(
|
||||
'Preferences/Appearance/updateTootPadding',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,46 +1,71 @@
|
|||
<template>
|
||||
<el-form class="pallet" label-position="top" size="small">
|
||||
<div class="item">
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.background_color') ">
|
||||
<el-color-picker v-model="background"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.selected_background_color')">
|
||||
<el-color-picker v-model="selectedBackground"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.global_header_color')">
|
||||
<el-color-picker v-model="globalHeader"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.side_menu_color')">
|
||||
<el-color-picker v-model="sideMenu"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.primary_color')">
|
||||
<el-color-picker v-model="primary"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.regular_color')">
|
||||
<el-color-picker v-model="regular"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.secondary_color')">
|
||||
<el-color-picker v-model="secondary"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.border_color')">
|
||||
<el-color-picker v-model="border"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.header_menu_color')">
|
||||
<el-color-picker v-model="headerMenu"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('preferences.appearance.custom_theme.wrapper_mask_color')">
|
||||
<el-color-picker v-model="wrapperMask" :show-alpha="true"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-form class="pallet" label-position="top" size="small">
|
||||
<div class="item">
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.background_color')"
|
||||
>
|
||||
<el-color-picker v-model="background"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="
|
||||
$t('preferences.appearance.custom_theme.selected_background_color')
|
||||
"
|
||||
>
|
||||
<el-color-picker v-model="selectedBackground"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.global_header_color')"
|
||||
>
|
||||
<el-color-picker v-model="globalHeader"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.side_menu_color')"
|
||||
>
|
||||
<el-color-picker v-model="sideMenu"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.primary_color')"
|
||||
>
|
||||
<el-color-picker v-model="primary"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.regular_color')"
|
||||
>
|
||||
<el-color-picker v-model="regular"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.secondary_color')"
|
||||
>
|
||||
<el-color-picker v-model="secondary"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.border_color')"
|
||||
>
|
||||
<el-color-picker v-model="border"></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.header_menu_color')"
|
||||
>
|
||||
<el-color-picker v-model="headerMenu"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('preferences.appearance.custom_theme.wrapper_mask_color')"
|
||||
>
|
||||
<el-color-picker
|
||||
v-model="wrapperMask"
|
||||
:show-alpha="true"
|
||||
></el-color-picker>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -48,106 +73,116 @@ export default {
|
|||
name: 'color-pallet',
|
||||
computed: {
|
||||
background: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.background_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.background_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
background_color: value
|
||||
background_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
selectedBackground: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.selected_background_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.selected_background_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
selected_background_color: value
|
||||
selected_background_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
globalHeader: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.global_header_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.global_header_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
global_header_color: value
|
||||
global_header_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
sideMenu: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.side_menu_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.side_menu_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
side_menu_color: value
|
||||
side_menu_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
primary: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.primary_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.primary_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
primary_color: value
|
||||
primary_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
regular: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.regular_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.regular_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
regular_color: value
|
||||
regular_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.secondary_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.secondary_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
secondary_color: value
|
||||
secondary_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
border: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.border_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.border_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
border_color: value
|
||||
border_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
headerMenu: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.header_menu_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.header_menu_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
header_menu_color: value
|
||||
header_menu_color: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
wrapperMask: {
|
||||
get () {
|
||||
return this.$store.state.Preferences.Appearance.appearance.customThemeColor.wrapper_mask_color
|
||||
get() {
|
||||
return this.$store.state.Preferences.Appearance.appearance
|
||||
.customThemeColor.wrapper_mask_color
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Appearance/updateCustomThemeColor', {
|
||||
wrapper_mask_color: value
|
||||
wrapper_mask_color: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -22,19 +22,31 @@
|
|||
<el-button type="text" class="reply" :title="$t('cards.toot.reply')">
|
||||
<font-awesome-icon icon="reply" size="sm" />
|
||||
</el-button>
|
||||
<el-button type="text" class="reblog" :title="$t('cards.toot.reblog')">
|
||||
<el-button
|
||||
type="text"
|
||||
class="reblog"
|
||||
:title="$t('cards.toot.reblog')"
|
||||
>
|
||||
<font-awesome-icon icon="retweet" size="sm" />
|
||||
</el-button>
|
||||
<span class="count">
|
||||
{{ reblogsCount }}
|
||||
</span>
|
||||
<el-button type="text" class="favourite" :title="$t('cards.toot.fav')">
|
||||
<el-button
|
||||
type="text"
|
||||
class="favourite"
|
||||
:title="$t('cards.toot.fav')"
|
||||
>
|
||||
<font-awesome-icon icon="star" size="sm" />
|
||||
</el-button>
|
||||
<span class="count">
|
||||
{{ favouritesCount }}
|
||||
</span>
|
||||
<popper trigger="click" :options="{ placement: 'bottom' }" ref="popper">
|
||||
<popper
|
||||
trigger="click"
|
||||
:options="{ placement: 'bottom' }"
|
||||
ref="popper"
|
||||
>
|
||||
<div class="popper toot-menu">
|
||||
<ul class="menu-list">
|
||||
<li role="button">
|
||||
|
@ -51,7 +63,11 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<el-button slot="reference" type="text" :title="$t('cards.toot.detail')">
|
||||
<el-button
|
||||
slot="reference"
|
||||
type="text"
|
||||
:title="$t('cards.toot.detail')"
|
||||
>
|
||||
<font-awesome-icon icon="ellipsis" size="sm" />
|
||||
</el-button>
|
||||
</popper>
|
||||
|
@ -75,12 +91,12 @@ export default {
|
|||
props: {
|
||||
displayNameStyle: {
|
||||
type: Number,
|
||||
default: DisplayStyle.DisplayNameAndUsername.value
|
||||
default: DisplayStyle.DisplayNameAndUsername.value,
|
||||
},
|
||||
timeFormat: {
|
||||
type: Number,
|
||||
default: TimeFormat.Absolute.value
|
||||
}
|
||||
default: TimeFormat.Absolute.value,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sampleIcon() {
|
||||
|
@ -119,8 +135,8 @@ export default {
|
|||
},
|
||||
favouritesCount() {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,37 +1,85 @@
|
|||
<template>
|
||||
<div id="general" v-loading="loading" :element-loading-background="backgroundColor">
|
||||
<div
|
||||
id="general"
|
||||
v-loading="loading"
|
||||
:element-loading-background="backgroundColor"
|
||||
>
|
||||
<h2>{{ $t('preferences.general.title') }}</h2>
|
||||
<el-form class="sounds section" label-position="right" label-width="250px" size="small">
|
||||
<el-form
|
||||
class="sounds section"
|
||||
label-position="right"
|
||||
label-width="250px"
|
||||
size="small"
|
||||
>
|
||||
<h3>{{ $t('preferences.general.sounds.title') }}</h3>
|
||||
<p class="description">{{ $t('preferences.general.sounds.description') }}</p>
|
||||
<el-form-item for="fav_rb" :label="$t('preferences.general.sounds.fav_rb')">
|
||||
<el-switch id="fav_rb" v-model="sound_fav_rb" active-color="#13ce66"> </el-switch>
|
||||
<p class="description">
|
||||
{{ $t('preferences.general.sounds.description') }}
|
||||
</p>
|
||||
<el-form-item
|
||||
for="fav_rb"
|
||||
:label="$t('preferences.general.sounds.fav_rb')"
|
||||
>
|
||||
<el-switch id="fav_rb" v-model="sound_fav_rb" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="sound_toot" :label="$t('preferences.general.sounds.toot')">
|
||||
<el-switch id="sound_toot" v-model="sound_toot" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="sound_toot"
|
||||
:label="$t('preferences.general.sounds.toot')"
|
||||
>
|
||||
<el-switch id="sound_toot" v-model="sound_toot" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="timeline section" label-potision="right" label-width="302px" size="samll">
|
||||
<el-form
|
||||
class="timeline section"
|
||||
label-potision="right"
|
||||
label-width="302px"
|
||||
size="samll"
|
||||
>
|
||||
<h3>{{ $t('preferences.general.timeline.title') }}</h3>
|
||||
<p class="description">{{ $t('preferences.general.timeline.description') }}</p>
|
||||
<p class="description">
|
||||
{{ $t('preferences.general.timeline.description') }}
|
||||
</p>
|
||||
<el-form-item for="cw" :label="$t('preferences.general.timeline.cw')">
|
||||
<el-switch id="cw" v-model="timeline_cw" active-color="#13ce66"> </el-switch>
|
||||
<el-switch id="cw" v-model="timeline_cw" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="nsfw" :label="$t('preferences.general.timeline.nsfw')">
|
||||
<el-switch id="nsfw" v-model="timeline_nsfw" active-color="#13ce66"> </el-switch>
|
||||
<el-switch id="nsfw" v-model="timeline_nsfw" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="hideAllAttachments" :label="$t('preferences.general.timeline.hideAllAttachments')">
|
||||
<el-switch id="hideAllAttachments" v-model="timeline_hide_attachments" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="hideAllAttachments"
|
||||
:label="$t('preferences.general.timeline.hideAllAttachments')"
|
||||
>
|
||||
<el-switch
|
||||
id="hideAllAttachments"
|
||||
v-model="timeline_hide_attachments"
|
||||
active-color="#13ce66"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="other section" label-position="right" label-width="250px" size="small" v-if="notDarwin">
|
||||
<el-form
|
||||
class="other section"
|
||||
label-position="right"
|
||||
label-width="250px"
|
||||
size="small"
|
||||
v-if="notDarwin"
|
||||
>
|
||||
<h3>{{ $t('preferences.general.other.title') }}</h3>
|
||||
<el-form-item for="launch" :label="$t('preferences.general.other.launch')">
|
||||
<el-switch id="launch" v-model="other_launch" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="launch"
|
||||
:label="$t('preferences.general.other.launch')"
|
||||
>
|
||||
<el-switch id="launch" v-model="other_launch" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="reset section">
|
||||
<el-button type="info" @click="reset">{{ $t('preferences.general.reset.button') }}</el-button>
|
||||
<el-button type="info" @click="reset">{{
|
||||
$t('preferences.general.reset.button')
|
||||
}}</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -43,10 +91,10 @@ export default {
|
|||
name: 'general',
|
||||
computed: {
|
||||
...mapState('Preferences/General', {
|
||||
loading: state => state.loading
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
...mapState({
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
...mapGetters('Preferences/General', ['notDarwin']),
|
||||
sound_fav_rb: {
|
||||
|
@ -55,9 +103,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateSound', {
|
||||
fav_rb: value
|
||||
fav_rb: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
sound_toot: {
|
||||
get() {
|
||||
|
@ -65,9 +113,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateSound', {
|
||||
toot: value
|
||||
toot: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
timeline_cw: {
|
||||
get() {
|
||||
|
@ -75,9 +123,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateTimeline', {
|
||||
cw: value
|
||||
cw: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
timeline_nsfw: {
|
||||
get() {
|
||||
|
@ -85,19 +133,20 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateTimeline', {
|
||||
nsfw: value
|
||||
nsfw: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
timeline_hide_attachments: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.General.general.timeline.hideAllAttachments
|
||||
return this.$store.state.Preferences.General.general.timeline
|
||||
.hideAllAttachments
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateTimeline', {
|
||||
hideAllAttachments: value
|
||||
hideAllAttachments: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
other_launch: {
|
||||
get() {
|
||||
|
@ -105,16 +154,16 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/General/updateOther', {
|
||||
launch: value
|
||||
launch: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Preferences/General/loadGeneral').catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.preferences_load_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
|
@ -122,17 +171,17 @@ export default {
|
|||
reset() {
|
||||
this.$store
|
||||
.dispatch('Preferences/General/reset')
|
||||
.then(language => {
|
||||
.then((language) => {
|
||||
this.$i18n.i18next.changeLanguage(language)
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.preferences_load_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,19 +3,35 @@
|
|||
<h2>{{ $t('preferences.language.title') }}</h2>
|
||||
<el-form class="display-language section" label-position="top" size="small">
|
||||
<h3>{{ $t('preferences.language.language.title') }}</h3>
|
||||
<el-form-item for="language" :label="$t('preferences.language.language.description')">
|
||||
<el-form-item
|
||||
for="language"
|
||||
:label="$t('preferences.language.language.description')"
|
||||
>
|
||||
<el-select id="language" v-model="displayLanguage" placeholder="style">
|
||||
<el-option v-for="lang in languages" :key="lang.key" :label="lang.name" :value="lang.key"> </el-option>
|
||||
<el-option
|
||||
v-for="lang in languages"
|
||||
:key="lang.key"
|
||||
:label="lang.name"
|
||||
:value="lang.key"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form class="spellchecker section" label-position="top" size="small">
|
||||
<h3>{{ $t('preferences.language.spellchecker.title') }}</h3>
|
||||
<el-form-item for="spellcheck" :label="$t('preferences.language.spellchecker.enabled')">
|
||||
<el-switch id="spellcheck" v-model="spellcheck" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="spellcheck"
|
||||
:label="$t('preferences.language.spellchecker.enabled')"
|
||||
>
|
||||
<el-switch id="spellcheck" v-model="spellcheck" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="spellcheck_languages">
|
||||
<el-checkbox-group id="spellcheck_languages" v-model="spellcheckLanguages">
|
||||
<el-checkbox-group
|
||||
id="spellcheck_languages"
|
||||
v-model="spellcheckLanguages"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="language in languages"
|
||||
:label="language.key"
|
||||
|
@ -56,8 +72,8 @@ export default {
|
|||
Language.sv_se,
|
||||
Language.tzm,
|
||||
Language.zh_cn,
|
||||
Language.zh_tw
|
||||
]
|
||||
Language.zh_tw,
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -66,36 +82,44 @@ export default {
|
|||
return this.$store.state.Preferences.Language.language.language
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Language/changeLanguage', value).then(key => {
|
||||
this.$i18n.i18next.changeLanguage(key)
|
||||
})
|
||||
}
|
||||
this.$store
|
||||
.dispatch('Preferences/Language/changeLanguage', value)
|
||||
.then((key) => {
|
||||
this.$i18n.i18next.changeLanguage(key)
|
||||
})
|
||||
},
|
||||
},
|
||||
spellcheck: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Language.language.spellchecker.enabled
|
||||
return this.$store.state.Preferences.Language.language.spellchecker
|
||||
.enabled
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Language/toggleSpellchecker', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
spellcheckLanguages: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Language.language.spellchecker.languages
|
||||
return this.$store.state.Preferences.Language.language.spellchecker
|
||||
.languages
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Language/updateSpellcheckerLanguages', value).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.language_not_support_spellchecker_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch('Preferences/Language/updateSpellcheckerLanguages', value)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t(
|
||||
'message.language_not_support_spellchecker_error'
|
||||
),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Preferences/Language/loadLanguage')
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,38 +3,100 @@
|
|||
<h2>{{ $t('preferences.network.proxy.title') }}</h2>
|
||||
<el-form class="network section" size="small" label-width="120px">
|
||||
<div class="proxy-source">
|
||||
<el-radio v-model="source" label="no">{{ $t('preferences.network.proxy.no') }}</el-radio>
|
||||
<el-radio v-model="source" label="no">{{
|
||||
$t('preferences.network.proxy.no')
|
||||
}}</el-radio>
|
||||
</div>
|
||||
<div class="proxy-source">
|
||||
<el-radio v-model="source" label="system">{{ $t('preferences.network.proxy.system') }}</el-radio>
|
||||
<el-radio v-model="source" label="system">{{
|
||||
$t('preferences.network.proxy.system')
|
||||
}}</el-radio>
|
||||
</div>
|
||||
<div class="proxy-source">
|
||||
<el-radio v-model="source" label="manual">{{ $t('preferences.network.proxy.manual') }}</el-radio>
|
||||
<el-radio v-model="source" label="manual">{{
|
||||
$t('preferences.network.proxy.manual')
|
||||
}}</el-radio>
|
||||
</div>
|
||||
<el-form-item for="proxyProtocol" :label="$t('preferences.network.proxy.protocol')">
|
||||
<el-select v-model="proxyProtocol" placeholder="Select protocol" :disabled="!manualProxyConfiguration">
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.http')" value="http"></el-option>
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.https')" value="https"></el-option>
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.socks4')" value="socks4"></el-option>
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.socks4a')" value="socks4a"></el-option>
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.socks5')" value="socks5"></el-option>
|
||||
<el-option :label="$t('preferences.network.proxy.protocol_list.socks5h')" value="socks5h"></el-option>
|
||||
<el-form-item
|
||||
for="proxyProtocol"
|
||||
:label="$t('preferences.network.proxy.protocol')"
|
||||
>
|
||||
<el-select
|
||||
v-model="proxyProtocol"
|
||||
placeholder="Select protocol"
|
||||
:disabled="!manualProxyConfiguration"
|
||||
>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.http')"
|
||||
value="http"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.https')"
|
||||
value="https"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.socks4')"
|
||||
value="socks4"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.socks4a')"
|
||||
value="socks4a"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.socks5')"
|
||||
value="socks5"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('preferences.network.proxy.protocol_list.socks5h')"
|
||||
value="socks5h"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item for="proxyHost" :label="$t('preferences.network.proxy.host')">
|
||||
<el-input v-model="proxyHost" :disabled="!manualProxyConfiguration" placeholder="proxy.example.com"></el-input>
|
||||
<el-form-item
|
||||
for="proxyHost"
|
||||
:label="$t('preferences.network.proxy.host')"
|
||||
>
|
||||
<el-input
|
||||
v-model="proxyHost"
|
||||
:disabled="!manualProxyConfiguration"
|
||||
placeholder="proxy.example.com"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item for="proxyPort" :label="$t('preferences.network.proxy.port')">
|
||||
<el-input v-model="proxyPort" :disabled="!manualProxyConfiguration" placeholder="8080"></el-input>
|
||||
<el-form-item
|
||||
for="proxyPort"
|
||||
:label="$t('preferences.network.proxy.port')"
|
||||
>
|
||||
<el-input
|
||||
v-model="proxyPort"
|
||||
:disabled="!manualProxyConfiguration"
|
||||
placeholder="8080"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item for="proxyUsername" :label="$t('preferences.network.proxy.username')">
|
||||
<el-input v-model="proxyUsername" :disabled="!manualProxyConfiguration" placeholder="username"></el-input>
|
||||
<el-form-item
|
||||
for="proxyUsername"
|
||||
:label="$t('preferences.network.proxy.username')"
|
||||
>
|
||||
<el-input
|
||||
v-model="proxyUsername"
|
||||
:disabled="!manualProxyConfiguration"
|
||||
placeholder="username"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item for="proxyPassword" :label="$t('preferences.network.proxy.password')">
|
||||
<el-input v-model="proxyPassword" :disabled="!manualProxyConfiguration" placeholder="password" show-password></el-input>
|
||||
<el-form-item
|
||||
for="proxyPassword"
|
||||
:label="$t('preferences.network.proxy.password')"
|
||||
>
|
||||
<el-input
|
||||
v-model="proxyPassword"
|
||||
:disabled="!manualProxyConfiguration"
|
||||
placeholder="password"
|
||||
show-password
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSave">{{ $t('preferences.network.save') }}</el-button>
|
||||
<el-button type="primary" @click="onSave">{{
|
||||
$t('preferences.network.save')
|
||||
}}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -53,7 +115,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/changeSource', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
proxyProtocol: {
|
||||
get() {
|
||||
|
@ -61,7 +123,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/updateProtocol', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
proxyHost: {
|
||||
get() {
|
||||
|
@ -69,7 +131,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/updateHost', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
proxyPort: {
|
||||
get() {
|
||||
|
@ -77,7 +139,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/updatePort', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
proxyUsername: {
|
||||
get() {
|
||||
|
@ -85,7 +147,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/updateUsername', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
proxyPassword: {
|
||||
get() {
|
||||
|
@ -93,22 +155,22 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Network/updatePassword', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Preferences/Network/loadProxy').catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.preferences_load_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onSave() {
|
||||
this.$store.dispatch('Preferences/Network/saveProxyConfig')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,34 +1,90 @@
|
|||
<template>
|
||||
<div id="notification">
|
||||
<h2>{{ $t('preferences.notification.title') }}</h2>
|
||||
<el-form class="section" label-position="right" label-width="360px" size="small">
|
||||
<p class="description">{{ $t('preferences.notification.enable.description') }}</p>
|
||||
<el-form-item for="notifyReply" :label="$t('preferences.notification.enable.reply')">
|
||||
<el-switch id="notifyReply" v-model="notifyReply" active-color="#13ce66"> </el-switch>
|
||||
<el-form
|
||||
class="section"
|
||||
label-position="right"
|
||||
label-width="360px"
|
||||
size="small"
|
||||
>
|
||||
<p class="description">
|
||||
{{ $t('preferences.notification.enable.description') }}
|
||||
</p>
|
||||
<el-form-item
|
||||
for="notifyReply"
|
||||
:label="$t('preferences.notification.enable.reply')"
|
||||
>
|
||||
<el-switch
|
||||
id="notifyReply"
|
||||
v-model="notifyReply"
|
||||
active-color="#13ce66"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyReblog" :label="$t('preferences.notification.enable.reblog')">
|
||||
<el-switch id="notifyReblog" v-model="notifyReblog" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="notifyReblog"
|
||||
:label="$t('preferences.notification.enable.reblog')"
|
||||
>
|
||||
<el-switch
|
||||
id="notifyReblog"
|
||||
v-model="notifyReblog"
|
||||
active-color="#13ce66"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyReaction" :label="$t('preferences.notification.enable.reaction')">
|
||||
<el-switch id="notifyReaction" v-model="notifyReaction" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="notifyReaction"
|
||||
:label="$t('preferences.notification.enable.reaction')"
|
||||
>
|
||||
<el-switch
|
||||
id="notifyReaction"
|
||||
v-model="notifyReaction"
|
||||
active-color="#13ce66"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyFavourite" :label="$t('preferences.notification.enable.favourite')">
|
||||
<el-switch id="notifyFavourite" v-model="notifyFavourite" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="notifyFavourite"
|
||||
:label="$t('preferences.notification.enable.favourite')"
|
||||
>
|
||||
<el-switch
|
||||
id="notifyFavourite"
|
||||
v-model="notifyFavourite"
|
||||
active-color="#13ce66"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyFollow" :label="$t('preferences.notification.enable.follow')">
|
||||
<el-form-item
|
||||
for="notifyFollow"
|
||||
:label="$t('preferences.notification.enable.follow')"
|
||||
>
|
||||
<el-switch v-model="notifyFollow" active-color="#13ce66"> </el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyFollowRequest" :label="$t('preferences.notification.enable.follow_request')">
|
||||
<el-switch v-model="notifyFollowRequest" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="notifyFollowRequest"
|
||||
:label="$t('preferences.notification.enable.follow_request')"
|
||||
>
|
||||
<el-switch v-model="notifyFollowRequest" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyStatus" :label="$t('preferences.notification.enable.status')">
|
||||
<el-form-item
|
||||
for="notifyStatus"
|
||||
:label="$t('preferences.notification.enable.status')"
|
||||
>
|
||||
<el-switch v-model="notifyStatus" active-color="#13ce66"> </el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyPollVote" :label="$t('preferences.notification.enable.poll_vote')">
|
||||
<el-form-item
|
||||
for="notifyPollVote"
|
||||
:label="$t('preferences.notification.enable.poll_vote')"
|
||||
>
|
||||
<el-switch v-model="notifyPollVote" active-color="#13ce66"> </el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item for="notifyPollExpired" :label="$t('preferences.notification.enable.poll_expired')">
|
||||
<el-switch v-model="notifyPollExpired" active-color="#13ce66"> </el-switch>
|
||||
<el-form-item
|
||||
for="notifyPollExpired"
|
||||
:label="$t('preferences.notification.enable.poll_expired')"
|
||||
>
|
||||
<el-switch v-model="notifyPollExpired" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -40,103 +96,114 @@ export default {
|
|||
computed: {
|
||||
notifyReply: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.reply
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.reply
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
reply: value
|
||||
reply: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyReblog: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.reblog
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.reblog
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
reblog: value
|
||||
reblog: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyFavourite: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.favourite
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.favourite
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
favourite: value
|
||||
favourite: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyFollow: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.follow
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.follow
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
follow: value
|
||||
follow: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyFollowRequest: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.follow_request
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.follow_request
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
follow_request: value
|
||||
follow_request: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyReaction: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.reaction
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.reaction
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
reaction: value
|
||||
reaction: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyStatus: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.status
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.status
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
status: value
|
||||
status: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyPollVote: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.poll_vote
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.poll_vote
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
poll_vote: value
|
||||
poll_vote: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
notifyPollExpired: {
|
||||
get() {
|
||||
return this.$store.state.Preferences.Notification.notification.notify.poll_expired
|
||||
return this.$store.state.Preferences.Notification.notification.notify
|
||||
.poll_expired
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Preferences/Notification/updateNotify', {
|
||||
poll_expired: value
|
||||
poll_expired: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Preferences/Notification/loadNotification').catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.preferences_load_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch('Preferences/Notification/loadNotification')
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.preferences_load_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
<h1>{{ $t('settings.title') }}</h1>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button type="text" icon="el-icon-close" @click="close" class="close-button" role="button"></el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
:icon="ElIconClose"
|
||||
@click="close"
|
||||
class="close-button"
|
||||
role="button"
|
||||
></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
|
@ -42,15 +48,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Close as ElIconClose } from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
ElIconClose,
|
||||
}
|
||||
},
|
||||
name: 'Settings',
|
||||
computed: {
|
||||
...mapState({
|
||||
primaryColor: state => state.App.theme.primary_color,
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
})
|
||||
primaryColor: (state) => state.App.theme.primary_color,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('Settings/changeAccountID', this.id())
|
||||
|
@ -65,8 +77,8 @@ export default {
|
|||
},
|
||||
activeRoute() {
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -17,17 +17,24 @@
|
|||
v-loading="filtersLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
>
|
||||
<el-table-column prop="phrase" label="Keyword" width="180"> </el-table-column>
|
||||
<el-table-column prop="phrase" label="Keyword" width="180">
|
||||
</el-table-column>
|
||||
<el-table-column label="Context">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ filters[scope.$index].context.join(',') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expires_at" label="Expires" width="180"> </el-table-column>
|
||||
<el-table-column prop="expires_at" label="Expires" width="180">
|
||||
</el-table-column>
|
||||
<el-table-column width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text">
|
||||
<router-link tag="span" :to="`/${id()}/settings/filters/${filters[scope.$index].id}/edit`">
|
||||
<router-link
|
||||
tag="span"
|
||||
:to="`/${id()}/settings/filters/${
|
||||
filters[scope.$index].id
|
||||
}/edit`"
|
||||
>
|
||||
{{ $t('settings.filters.edit.title') }}
|
||||
</router-link>
|
||||
</el-button>
|
||||
|
@ -35,7 +42,10 @@
|
|||
</el-table-column>
|
||||
<el-table-column width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="deleteFilter(filters[scope.$index].id)">
|
||||
<el-button
|
||||
type="text"
|
||||
@click="deleteFilter(filters[scope.$index].id)"
|
||||
>
|
||||
{{ $t('settings.filters.delete.title') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -52,15 +62,15 @@ export default {
|
|||
name: 'Filters',
|
||||
computed: {
|
||||
...mapState('Settings/Filters', {
|
||||
filters: state => state.filters,
|
||||
filtersLoading: state => state.filtersLoading
|
||||
filters: (state) => state.filters,
|
||||
filtersLoading: (state) => state.filtersLoading,
|
||||
}),
|
||||
...mapState({
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
sns: state => state.sns
|
||||
})
|
||||
sns: (state) => state.sns,
|
||||
}),
|
||||
},
|
||||
async created() {
|
||||
await this.$store.dispatch('Settings/Filters/fetchFilters')
|
||||
|
@ -73,12 +83,12 @@ export default {
|
|||
this.$confirm(this.$t('settings.filters.delete.confirm'), 'Warning', {
|
||||
confirmButtonText: this.$t('settings.filters.delete.confirm_ok'),
|
||||
cancelButtonText: this.$t('settings.filters.delete.confirm_cancel'),
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
return this.$store.dispatch('Settings/Filters/deleteFilter', id)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div id="edit_filter">
|
||||
<h2>{{ $t('settings.filters.edit.title') }}</h2>
|
||||
<FilterForm v-model="filter" @cancel="cancel" @onSubmit="onSubmit" :loading="loading" :sns="sns"> </FilterForm>
|
||||
<FilterForm
|
||||
v-model="filter"
|
||||
@cancel="cancel"
|
||||
@onSubmit="onSubmit"
|
||||
:loading="loading"
|
||||
:sns="sns"
|
||||
>
|
||||
</FilterForm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -15,10 +22,10 @@ export default {
|
|||
components: { FilterForm },
|
||||
computed: {
|
||||
...mapState('Settings/Filters/Edit', {
|
||||
loading: state => state.loading
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
sns: state => state.sns
|
||||
sns: (state) => state.sns,
|
||||
}),
|
||||
filter: {
|
||||
get() {
|
||||
|
@ -26,11 +33,14 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Filters/Edit/editFilter', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.$store.dispatch('Settings/Filters/Edit/fetchFilter', this.filter_id)
|
||||
await this.$store.dispatch(
|
||||
'Settings/Filters/Edit/fetchFilter',
|
||||
this.filter_id
|
||||
)
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
|
@ -42,14 +52,14 @@ export default {
|
|||
.then(() => {
|
||||
this.$router.go(-1)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.update_filter_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div id="new_filter">
|
||||
<h2>{{ $t('settings.filters.new.title') }}</h2>
|
||||
<FilterForm v-model="filter" @cancel="cancel" @onSubmit="onSubmit" :loading="loading" :sns="sns"> </FilterForm>
|
||||
<FilterForm
|
||||
v-model="filter"
|
||||
@cancel="cancel"
|
||||
@onSubmit="onSubmit"
|
||||
:loading="loading"
|
||||
:sns="sns"
|
||||
>
|
||||
</FilterForm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -14,10 +21,10 @@ export default {
|
|||
components: { FilterForm },
|
||||
computed: {
|
||||
...mapState('Settings/Filters/New', {
|
||||
loading: state => state.loading
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
sns: state => state.sns
|
||||
sns: (state) => state.sns,
|
||||
}),
|
||||
filter: {
|
||||
get() {
|
||||
|
@ -25,8 +32,8 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Filters/New/editFilter', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
|
@ -38,14 +45,14 @@ export default {
|
|||
.then(() => {
|
||||
this.$router.go(-1)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.create_filter_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
<template>
|
||||
<el-form ref="form" class="section" label-width="200px" label-position="right" size="medium">
|
||||
<el-form
|
||||
ref="form"
|
||||
class="section"
|
||||
label-width="200px"
|
||||
label-position="right"
|
||||
size="medium"
|
||||
>
|
||||
<el-form-item :label="$t('settings.filters.form.phrase')">
|
||||
<el-input v-model="filterPhrase"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('settings.filters.form.expire')">
|
||||
<el-select v-model="filterExpire" value-key="value">
|
||||
<el-option v-for="exp in expires" :key="exp.value" :label="exp.label" :value="exp"> </el-option>
|
||||
<el-option
|
||||
v-for="exp in expires"
|
||||
:key="exp.value"
|
||||
:label="exp.label"
|
||||
:value="exp"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('settings.filters.form.context')">
|
||||
|
@ -15,19 +27,30 @@
|
|||
<el-checkbox label="notifications"></el-checkbox>
|
||||
<el-checkbox label="public"></el-checkbox>
|
||||
<el-checkbox label="thread"></el-checkbox>
|
||||
<el-checkbox label="account" :disabled="accountDisabled()"></el-checkbox>
|
||||
<el-checkbox
|
||||
label="account"
|
||||
:disabled="accountDisabled()"
|
||||
></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="filterIrreversible">{{ $t('settings.filters.form.irreversible') }}</el-checkbox>
|
||||
<el-checkbox v-model="filterIrreversible">{{
|
||||
$t('settings.filters.form.irreversible')
|
||||
}}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="filterWholeWord">{{ $t('settings.filters.form.whole_word') }}</el-checkbox>
|
||||
<el-checkbox v-model="filterWholeWord">{{
|
||||
$t('settings.filters.form.whole_word')
|
||||
}}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit" v-loading="loading">{{ $t('settings.filters.form.submit') }}</el-button>
|
||||
<el-button @click="cancel">{{ $t('settings.filters.form.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="onSubmit" v-loading="loading">{{
|
||||
$t('settings.filters.form.submit')
|
||||
}}</el-button>
|
||||
<el-button @click="cancel">{{
|
||||
$t('settings.filters.form.cancel')
|
||||
}}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
@ -38,48 +61,48 @@ export default {
|
|||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
type: Object
|
||||
type: Object,
|
||||
},
|
||||
sns: {
|
||||
type: String,
|
||||
default: 'mastodon'
|
||||
}
|
||||
default: 'mastodon',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expires: [
|
||||
{
|
||||
label: this.$t('settings.filters.expires.never'),
|
||||
value: null
|
||||
value: null,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.30_minutes'),
|
||||
value: 60 * 30
|
||||
value: 60 * 30,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_hour'),
|
||||
value: 3600
|
||||
value: 3600,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.6_hours'),
|
||||
value: 3600 * 6
|
||||
value: 3600 * 6,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.12_hours'),
|
||||
value: 3600 * 12
|
||||
value: 3600 * 12,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
value: 3600 * 24,
|
||||
},
|
||||
{
|
||||
label: this.$t('settings.filters.expires.1_week'),
|
||||
value: 3600 * 24 * 7
|
||||
}
|
||||
]
|
||||
value: 3600 * 24 * 7,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -89,7 +112,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
filterPhrase: {
|
||||
get() {
|
||||
|
@ -97,9 +120,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
phrase: value
|
||||
phrase: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
filterExpire: {
|
||||
get() {
|
||||
|
@ -107,9 +130,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
expires_at: value
|
||||
expires_at: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
filterContext: {
|
||||
get() {
|
||||
|
@ -117,9 +140,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
context: value
|
||||
context: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
filterIrreversible: {
|
||||
get() {
|
||||
|
@ -127,9 +150,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
irreversible: value
|
||||
irreversible: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
filterWholeWord: {
|
||||
get() {
|
||||
|
@ -137,10 +160,10 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.filter = Object.assign({}, this.filter, {
|
||||
whole_word: value
|
||||
whole_word: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
|
@ -151,8 +174,8 @@ export default {
|
|||
},
|
||||
accountDisabled() {
|
||||
return this.sns === 'pleroma'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
<template>
|
||||
<div id="general">
|
||||
<h2>{{ $t('settings.general.title') }}</h2>
|
||||
<el-form class="toot section" label-width="250px" label-position="right" size="medium">
|
||||
<el-form
|
||||
class="toot section"
|
||||
label-width="250px"
|
||||
label-position="right"
|
||||
size="medium"
|
||||
>
|
||||
<h3>{{ $t('settings.general.toot.title') }}</h3>
|
||||
<el-form-item for="visibility" :label="$t('settings.general.toot.visibility.description')">
|
||||
<el-select id="visibility" v-model="tootVisibility" placeholder="visibility">
|
||||
<el-option v-for="v in visibilities" :key="v.value" :label="$t(v.name)" :value="v.value"> </el-option>
|
||||
<el-form-item
|
||||
for="visibility"
|
||||
:label="$t('settings.general.toot.visibility.description')"
|
||||
>
|
||||
<el-select
|
||||
id="visibility"
|
||||
v-model="tootVisibility"
|
||||
placeholder="visibility"
|
||||
>
|
||||
<el-option
|
||||
v-for="v in visibilities"
|
||||
:key="v.value"
|
||||
:label="$t(v.name)"
|
||||
:value="v.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<p class="notice">{{ $t('settings.general.toot.visibility.notice') }}</p>
|
||||
<p class="notice">
|
||||
{{ $t('settings.general.toot.visibility.notice') }}
|
||||
</p>
|
||||
</el-form-item>
|
||||
<el-form-item for="sensitive" :label="$t('settings.general.toot.sensitive.description')">
|
||||
<el-form-item
|
||||
for="sensitive"
|
||||
:label="$t('settings.general.toot.sensitive.description')"
|
||||
>
|
||||
<el-switch id="sensitive" v-model="tootSensitive"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -23,7 +46,11 @@ export default {
|
|||
name: 'General',
|
||||
data() {
|
||||
return {
|
||||
visibilities: [Visibility.Public, Visibility.Unlisted, Visibility.Private]
|
||||
visibilities: [
|
||||
Visibility.Public,
|
||||
Visibility.Unlisted,
|
||||
Visibility.Private,
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -33,7 +60,7 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/General/setVisibility', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
tootSensitive: {
|
||||
get() {
|
||||
|
@ -41,12 +68,12 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/General/setSensitive', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('Settings/General/fetchSettings')
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,30 +1,60 @@
|
|||
<template>
|
||||
<div id="timeline">
|
||||
<h2>{{ $t('settings.timeline.title') }}</h2>
|
||||
<el-form class="unread-notification section" size="medium" label-position="right" label-width="250px">
|
||||
<el-form
|
||||
class="unread-notification section"
|
||||
size="medium"
|
||||
label-position="right"
|
||||
label-width="250px"
|
||||
>
|
||||
<h3>{{ $t('settings.timeline.unread_notification.title') }}</h3>
|
||||
<p class="description">{{ $t('settings.timeline.unread_notification.description') }}</p>
|
||||
<p class="description">
|
||||
{{ $t('settings.timeline.unread_notification.description') }}
|
||||
</p>
|
||||
|
||||
<el-form-item for="direct" :label="$t('settings.timeline.unread_notification.direct')">
|
||||
<el-form-item
|
||||
for="direct"
|
||||
:label="$t('settings.timeline.unread_notification.direct')"
|
||||
>
|
||||
<el-switch v-model="direct" id="direct" />
|
||||
</el-form-item>
|
||||
<el-form-item for="local" :label="$t('settings.timeline.unread_notification.local')">
|
||||
<el-form-item
|
||||
for="local"
|
||||
:label="$t('settings.timeline.unread_notification.local')"
|
||||
>
|
||||
<el-switch v-model="local" id="local" />
|
||||
</el-form-item>
|
||||
<el-form-item for="public" :label="$t('settings.timeline.unread_notification.public')">
|
||||
<el-form-item
|
||||
for="public"
|
||||
:label="$t('settings.timeline.unread_notification.public')"
|
||||
>
|
||||
<el-switch v-model="public" id="public" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-form class="use-marker section" size="medium" label-position="right" label-width="250px">
|
||||
<el-form
|
||||
class="use-marker section"
|
||||
size="medium"
|
||||
label-position="right"
|
||||
label-width="250px"
|
||||
>
|
||||
<h3>{{ $t('settings.timeline.use_marker.title') }}</h3>
|
||||
<el-form-item for="marker_home" :label="$t('settings.timeline.use_marker.home')">
|
||||
<el-form-item
|
||||
for="marker_home"
|
||||
:label="$t('settings.timeline.use_marker.home')"
|
||||
>
|
||||
<el-switch v-model="marker_home" id="marker_home" />
|
||||
</el-form-item>
|
||||
<el-form-item for="marker_notifications" :label="$t('settings.timeline.use_marker.notifications')">
|
||||
<el-form-item
|
||||
for="marker_notifications"
|
||||
:label="$t('settings.timeline.use_marker.notifications')"
|
||||
>
|
||||
<el-switch v-model="marker_notifications" id="marker_notifications" />
|
||||
</el-form-item>
|
||||
<el-form-item for="marker_mentions" :label="$t('settings.timeline.use_marker.mentions')">
|
||||
<el-form-item
|
||||
for="marker_mentions"
|
||||
:label="$t('settings.timeline.use_marker.mentions')"
|
||||
>
|
||||
<el-switch v-model="marker_mentions" id="marker_mentions" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -37,33 +67,36 @@ export default {
|
|||
computed: {
|
||||
direct: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification.direct
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification
|
||||
.direct
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUnreadNotification', {
|
||||
direct: value
|
||||
direct: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
local: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification.local
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification
|
||||
.local
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUnreadNotification', {
|
||||
local: value
|
||||
local: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
public: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification.public
|
||||
return this.$store.state.Settings.Timeline.setting.unreadNotification
|
||||
.public
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUnreadNotification', {
|
||||
public: value
|
||||
public: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
marker_home: {
|
||||
get() {
|
||||
|
@ -71,19 +104,20 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUseMarker', {
|
||||
home: value
|
||||
home: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
marker_notifications: {
|
||||
get() {
|
||||
return this.$store.state.Settings.Timeline.setting.useMarker.notifications
|
||||
return this.$store.state.Settings.Timeline.setting.useMarker
|
||||
.notifications
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUseMarker', {
|
||||
notifications: value
|
||||
notifications: value,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
marker_mentions: {
|
||||
get() {
|
||||
|
@ -91,14 +125,14 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('Settings/Timeline/changeUseMarker', {
|
||||
mentions: value
|
||||
mentions: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.$store.dispatch('Settings/Timeline/loadTimelineSetting')
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -39,18 +39,18 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
dropTarget: null,
|
||||
droppableVisible: false
|
||||
droppableVisible: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
loading: state => state.TimelineSpace.loading,
|
||||
collapse: state => state.TimelineSpace.SideMenu.collapse
|
||||
loading: (state) => state.TimelineSpace.loading,
|
||||
collapse: (state) => state.TimelineSpace.SideMenu.collapse,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
return !this.modalOpened
|
||||
}
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/close')
|
||||
|
@ -88,17 +88,20 @@ export default {
|
|||
await this.clear()
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/initLoad', this.$route.params.id)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/initLoad',
|
||||
this.$route.params.id
|
||||
)
|
||||
} catch (err) {
|
||||
if (err instanceof AccountLoadError) {
|
||||
this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else if (err instanceof TimelineFetchError) {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -109,14 +112,17 @@ export default {
|
|||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
this.droppableVisible = false
|
||||
if (e.dataTransfer.files.item(0) === null || e.dataTransfer.files.item(0) === undefined) {
|
||||
if (
|
||||
e.dataTransfer.files.item(0) === null ||
|
||||
e.dataTransfer.files.item(0) === undefined
|
||||
) {
|
||||
return false
|
||||
}
|
||||
const file = e.dataTransfer.files.item(0)
|
||||
if (!file.type.includes('image') && !file.type.includes('video')) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_image'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
@ -127,16 +133,16 @@ export default {
|
|||
.then(() => {
|
||||
Event.$emit('image-uploaded')
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
if (err instanceof NewTootAttachLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.attach_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -162,8 +168,8 @@ export default {
|
|||
this.$store.commit('TimelineSpace/Modals/Shortcut/changeModal', true)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
<template>
|
||||
<div id="contents" ref="contents" :style="customWidth" @mouseup="dragEnd" @mousemove="resize">
|
||||
<div
|
||||
id="contents"
|
||||
ref="contents"
|
||||
:style="customWidth"
|
||||
@mouseup="dragEnd"
|
||||
@mousemove="resize"
|
||||
>
|
||||
<div
|
||||
:class="openSideBar ? 'timeline-wrapper-with-side-bar' : 'timeline-wrapper'"
|
||||
:class="
|
||||
openSideBar ? 'timeline-wrapper-with-side-bar' : 'timeline-wrapper'
|
||||
"
|
||||
v-loading="loading"
|
||||
:element-loading-text="$t('message.loading')"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
|
@ -34,25 +42,25 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
sidebarWidth: 360,
|
||||
dragging: false
|
||||
dragging: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SideBar
|
||||
SideBar,
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents', {
|
||||
loading: state => state.loading
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/SideBar', {
|
||||
openSideBar: state => state.openSideBar
|
||||
openSideBar: (state) => state.openSideBar,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
customWidth: function () {
|
||||
return {
|
||||
'--current-sidebar-width': `${this.sidebarWidth}px`
|
||||
'--current-sidebar-width': `${this.sidebarWidth}px`,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resize(event) {
|
||||
|
@ -67,8 +75,8 @@ export default {
|
|||
dragEnd() {
|
||||
this.dragging = false
|
||||
this.$refs.contents.style.setProperty('user-select', 'text')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<template>
|
||||
<div id="bookmarks" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="bookmarks" :min-item-size="60" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="bookmarks"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="bookmarks"
|
||||
:min-item-size="60"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri === focusedId"
|
||||
|
@ -19,49 +38,55 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import Toot from '@/components/organisms/Toot'
|
||||
import reloadable from '~/src/renderer/components/mixins/reloadable'
|
||||
import { Event } from '~/src/renderer/components/event'
|
||||
|
||||
export default {
|
||||
name: 'bookmarks',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
heading: true,
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'bookmarks',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('TimelineSpace', {
|
||||
account: state => state.account
|
||||
account: (state) => state.account,
|
||||
}),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
...mapState('TimelineSpace/HeaderMenu', {
|
||||
startReload: state => state.reload
|
||||
startReload: (state) => state.reload,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/SideBar', {
|
||||
openSideBar: state => state.openSideBar
|
||||
openSideBar: (state) => state.openSideBar,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/Bookmarks', {
|
||||
bookmarks: state => state.bookmarks,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
bookmarks: (state) => state.bookmarks,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
return !this.focusedId && !this.modalOpened
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
|
@ -70,7 +95,7 @@ export default {
|
|||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -78,7 +103,9 @@ export default {
|
|||
})
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
const previousFocusedId = this.focusedId
|
||||
|
@ -93,8 +120,13 @@ export default {
|
|||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Bookmarks/updateBookmarks', [])
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -112,7 +144,7 @@ export default {
|
|||
} else if (newState === null && !this.heading) {
|
||||
this.heading = true
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateToot(message) {
|
||||
|
@ -123,15 +155,21 @@ export default {
|
|||
},
|
||||
onScroll(event) {
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Bookmarks/lazyFetchBookmarks', this.bookmarks[this.bookmarks.length - 1]).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Bookmarks/lazyFetchBookmarks',
|
||||
this.bookmarks[this.bookmarks.length - 1]
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
// for upper
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
|
@ -144,12 +182,14 @@ export default {
|
|||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
try {
|
||||
const account = await this.reloadable()
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Bookmarks/fetchBookmarks', account).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/Bookmarks/fetchBookmarks', account)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/changeLoading', false)
|
||||
}
|
||||
|
@ -159,7 +199,9 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.bookmarks.findIndex(toot => this.focusedId === toot.uri)
|
||||
const currentIndex = this.bookmarks.findIndex(
|
||||
(toot) => this.focusedId === toot.uri
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.bookmarks[0].uri
|
||||
} else if (currentIndex < this.bookmarks.length) {
|
||||
|
@ -167,7 +209,9 @@ export default {
|
|||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.bookmarks.findIndex(toot => this.focusedId === toot.uri)
|
||||
const currentIndex = this.bookmarks.findIndex(
|
||||
(toot) => this.focusedId === toot.uri
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
|
@ -186,8 +230,8 @@ export default {
|
|||
this.focusedId = this.bookmarks[0].uri
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<template>
|
||||
<div id="directmessages" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="directmessages"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -21,13 +40,18 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -36,30 +60,32 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'directmessages',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
scrollPosition: null,
|
||||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null
|
||||
resizeTime: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'directmessages',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/DirectMessages', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
scrolling: state => state.scrolling
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: state => state.TimelineSpace.timelineSetting.unreadNotification
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: (state) =>
|
||||
state.TimelineSpace.timelineSetting.unreadNotification,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
|
@ -70,16 +96,23 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline', false)
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline',
|
||||
false
|
||||
)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
if (!this.unreadNotification.direct) {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
await this.initialize().finally(_ => {
|
||||
await this.initialize().finally((_) => {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
})
|
||||
}
|
||||
|
@ -97,18 +130,31 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
|
||||
if (
|
||||
this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadDirectMessagesTimeline && this.heading) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline', false)
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadDirectMessagesTimeline &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadDirectMessagesTimeline',
|
||||
false
|
||||
)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
this.scrollPosition.prepare()
|
||||
|
@ -123,13 +169,21 @@ export default {
|
|||
this.observer.disconnect()
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/archiveTimeline')
|
||||
if (!this.unreadNotification.direct) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/clearTimeline')
|
||||
}
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -143,20 +197,28 @@ export default {
|
|||
},
|
||||
focusedId: function (newState, _oldState) {
|
||||
if (newState && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async initialize() {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/DirectMessages/fetchTimeline').catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/DirectMessages/fetchTimeline')
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
await this.$store.dispatch('TimelineSpace/bindDirectMessagesStreaming')
|
||||
this.$store.dispatch('TimelineSpace/startDirectMessagesStreaming')
|
||||
},
|
||||
|
@ -166,54 +228,82 @@ export default {
|
|||
}
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/DirectMessages/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
|
||||
.then(statuses => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/DirectMessages/lazyFetchTimeline',
|
||||
this.timeline[this.timeline.length - 1]
|
||||
)
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (event.target.scrollTop <= 10 && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/deleteToot', message.id)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/deleteToot',
|
||||
message.id
|
||||
)
|
||||
},
|
||||
async reload() {
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
|
@ -228,19 +318,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -257,12 +355,18 @@ export default {
|
|||
}
|
||||
},
|
||||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/DirectMessages/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/DirectMessages/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -299,4 +403,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<template>
|
||||
<div id="favourites" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="favourites" :min-item-size="60" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="favourites"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="favourites"
|
||||
:min-item-size="60"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri === focusedId"
|
||||
|
@ -20,50 +39,60 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
import reloadable from '~/src/renderer/components/mixins/reloadable'
|
||||
import { Event } from '~/src/renderer/components/event'
|
||||
|
||||
export default {
|
||||
name: 'favourites',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
heading: true,
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'favourites',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
account: state => state.TimelineSpace.account,
|
||||
favourites: state => state.TimelineSpace.Contents.Favourites.favourites,
|
||||
lazyLoading: state => state.TimelineSpace.Contents.Favourites.lazyLoading
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
account: (state) => state.TimelineSpace.account,
|
||||
favourites: (state) => state.TimelineSpace.Contents.Favourites.favourites,
|
||||
lazyLoading: (state) =>
|
||||
state.TimelineSpace.Contents.Favourites.lazyLoading,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
return !this.focusedId && !this.modalOpened
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Favourites/fetchFavourites', this.account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Favourites/fetchFavourites',
|
||||
this.account
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.favourite_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -71,7 +100,9 @@ export default {
|
|||
})
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
const previousFocusedId = this.focusedId
|
||||
|
@ -86,8 +117,13 @@ export default {
|
|||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Favourites/updateFavourites', [])
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -105,26 +141,36 @@ export default {
|
|||
} else if (newState === null && !this.heading) {
|
||||
this.heading = true
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/Favourites/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Favourites/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/Favourites/deleteToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Favourites/deleteToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
onScroll(event) {
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Favourites/lazyFetchFavourites', this.favourites[this.favourites.length - 1])
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Favourites/lazyFetchFavourites',
|
||||
this.favourites[this.favourites.length - 1]
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.favourite_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -139,12 +185,17 @@ export default {
|
|||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
try {
|
||||
const account = await this.reloadable()
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Favourites/fetchFavourites', account).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.favourite_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Favourites/fetchFavourites',
|
||||
account
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.favourite_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/changeLoading', false)
|
||||
}
|
||||
|
@ -154,7 +205,9 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.favourites.findIndex(toot => this.focusedId === toot.uri)
|
||||
const currentIndex = this.favourites.findIndex(
|
||||
(toot) => this.focusedId === toot.uri
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.favourites[0].uri
|
||||
} else if (currentIndex < this.favourites.length) {
|
||||
|
@ -162,7 +215,9 @@ export default {
|
|||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.favourites.findIndex(toot => this.focusedId === toot.uri)
|
||||
const currentIndex = this.favourites.findIndex(
|
||||
(toot) => this.focusedId === toot.uri
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
|
@ -181,8 +236,8 @@ export default {
|
|||
this.focusedId = this.favourites[0].uri
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<div id="follow-requests">
|
||||
<template v-for="account in requests">
|
||||
<user :user="account" :request="true" @acceptRequest="accept" @rejectRequest="reject"></user>
|
||||
<user
|
||||
:user="account"
|
||||
:request="true"
|
||||
@acceptRequest="accept"
|
||||
@rejectRequest="reject"
|
||||
></user>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -15,39 +20,49 @@ export default {
|
|||
components: { User },
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/FollowRequests', {
|
||||
requests: state => state.requests
|
||||
})
|
||||
requests: (state) => state.requests,
|
||||
}),
|
||||
},
|
||||
async mounted() {
|
||||
await this.initialize()
|
||||
},
|
||||
methods: {
|
||||
async initialize() {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/FollowRequests/fetchRequests').catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/FollowRequests/fetchRequests')
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
accept(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/FollowRequests/acceptRequest', account).catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_request_accept_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/FollowRequests/acceptRequest',
|
||||
account
|
||||
)
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_request_accept_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
reject(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/FollowRequests/rejectRequest', account).catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_request_reject_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/FollowRequests/rejectRequest',
|
||||
account
|
||||
)
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_request_reject_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scorped></style>
|
||||
|
|
|
@ -19,7 +19,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="form-item" v-show="tagPage()">
|
||||
<el-button type="text" @click="save" :title="$t('hashtag.save_tag')">
|
||||
<el-button
|
||||
type="text"
|
||||
@click="save"
|
||||
:title="$t('hashtag.save_tag')"
|
||||
>
|
||||
<font-awesome-icon icon="thumbtack" />
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -35,7 +39,7 @@ export default {
|
|||
name: 'hashtag',
|
||||
data() {
|
||||
return {
|
||||
tag: ''
|
||||
tag: '',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -48,7 +52,7 @@ export default {
|
|||
if (route.name === 'tag') {
|
||||
this.tag = route.params.tag
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
id() {
|
||||
|
@ -65,8 +69,8 @@ export default {
|
|||
},
|
||||
save() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/saveTag', this.tag)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,12 +2,20 @@
|
|||
<div id="list">
|
||||
<table class="tag-list">
|
||||
<tbody>
|
||||
<tr v-for="tag in tags" v-bind:key="tag._id" @click.stop.prevent="openTimeline(tag.tagName)">
|
||||
<tr
|
||||
v-for="tag in tags"
|
||||
v-bind:key="tag._id"
|
||||
@click.stop.prevent="openTimeline(tag.tagName)"
|
||||
>
|
||||
<td>
|
||||
{{ tag.tagName }}
|
||||
</td>
|
||||
<td class="action">
|
||||
<el-button type="text" @click.stop="deleteTag(tag)" :title="$t('hashtag.delete_tag')">
|
||||
<el-button
|
||||
type="text"
|
||||
@click.stop="deleteTag(tag)"
|
||||
:title="$t('hashtag.delete_tag')"
|
||||
>
|
||||
<font-awesome-icon :icon="['far', 'trash-can']" />
|
||||
</el-button>
|
||||
</td>
|
||||
|
@ -24,20 +32,22 @@ export default {
|
|||
name: 'list',
|
||||
computed: {
|
||||
...mapState({
|
||||
tags: state => state.TimelineSpace.Contents.Hashtag.List.tags
|
||||
})
|
||||
tags: (state) => state.TimelineSpace.Contents.Hashtag.List.tags,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/List/listTags')
|
||||
},
|
||||
methods: {
|
||||
openTimeline(tagName) {
|
||||
this.$router.push({ path: `/${this.$route.params.id}/hashtag/${tagName}` })
|
||||
this.$router.push({
|
||||
path: `/${this.$route.params.id}/hashtag/${tagName}`,
|
||||
})
|
||||
},
|
||||
deleteTag(tag) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/List/removeTag', tag)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,9 +1,29 @@
|
|||
<template>
|
||||
<div name="tag" class="tag-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
name="tag"
|
||||
class="tag-timeline"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -21,13 +41,18 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -36,28 +61,30 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'tag',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
props: ['tag'],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
scrollPosition: null,
|
||||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null
|
||||
resizeTime: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'tag',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
props: ['tag'],
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
timeline: state => state.TimelineSpace.Contents.Hashtag.Tag.timeline,
|
||||
lazyLoading: state => state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading,
|
||||
heading: state => state.TimelineSpace.Contents.Hashtag.Tag.heading,
|
||||
scrolling: state => state.TimelineSpace.Contents.Hashtag.Tag.scrolling
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
timeline: (state) => state.TimelineSpace.Contents.Hashtag.Tag.timeline,
|
||||
lazyLoading: (state) =>
|
||||
state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading,
|
||||
heading: (state) => state.TimelineSpace.Contents.Hashtag.Tag.heading,
|
||||
scrolling: (state) => state.TimelineSpace.Contents.Hashtag.Tag.scrolling,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
|
@ -68,16 +95,20 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
this.load(this.tag).finally(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
})
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
|
@ -92,13 +123,20 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
|
||||
if (
|
||||
this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
|
@ -123,11 +161,17 @@ export default {
|
|||
},
|
||||
focusedId: function (newState, _oldState) {
|
||||
if (newState && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/stopStreaming')
|
||||
|
@ -137,26 +181,38 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async load(tag) {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
return true
|
||||
},
|
||||
reset() {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/archiveTimeline')
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/clearTimeline')
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -164,7 +220,10 @@ export default {
|
|||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/updateToot', toot)
|
||||
},
|
||||
deleteToot(toot) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/deleteToot', toot.id)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/deleteToot',
|
||||
toot.id
|
||||
)
|
||||
},
|
||||
onScroll(event) {
|
||||
if (moment().diff(this.resizeTime) < 500) {
|
||||
|
@ -172,48 +231,67 @@ export default {
|
|||
}
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Hashtag/Tag/lazyFetchTimeline', {
|
||||
tag: this.tag,
|
||||
status: this.timeline[this.timeline.length - 1]
|
||||
status: this.timeline[this.timeline.length - 1],
|
||||
})
|
||||
.then(statuses => {
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (event.target.scrollTop <= 10 && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
|
@ -222,19 +300,25 @@ export default {
|
|||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
try {
|
||||
await this.reloadable()
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/stopStreaming')
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/stopStreaming'
|
||||
)
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/Hashtag/Tag/fetch', tag)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$store.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Hashtag/Tag/startStreaming', tag)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/changeLoading', false)
|
||||
}
|
||||
|
@ -244,19 +328,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -273,12 +365,18 @@ export default {
|
|||
}
|
||||
},
|
||||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Hashtag/Tag/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -306,4 +404,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,15 +1,45 @@
|
|||
<template>
|
||||
<div id="home" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="filteredTimeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="home"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="filteredTimeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<template v-if="item.id === 'loading-card'">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
|
||||
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchTimelineSince" />
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.id]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<StatusLoading
|
||||
:since_id="item.since_id"
|
||||
:max_id="item.max_id"
|
||||
:loading="loadingMore"
|
||||
@load_since="fetchTimelineSince"
|
||||
/>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -29,13 +59,18 @@
|
|||
</template>
|
||||
</DynamicScroller>
|
||||
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -45,9 +80,6 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
components: { Toot, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
|
@ -55,22 +87,26 @@ export default {
|
|||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null,
|
||||
loadingMore: false
|
||||
loadingMore: false,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'home',
|
||||
components: { Toot, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/Home', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
showReblogs: state => state.showReblogs,
|
||||
showReplies: state => state.showReplies,
|
||||
scrolling: state => state.scrolling
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
showReblogs: (state) => state.showReblogs,
|
||||
showReplies: (state) => state.showReplies,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapState({
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
...mapGetters('TimelineSpace/Contents/Home', ['filters']),
|
||||
|
@ -82,11 +118,13 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
},
|
||||
filteredTimeline() {
|
||||
return this.timeline.filter(toot => {
|
||||
return this.timeline.filter((toot) => {
|
||||
if (toot.in_reply_to_id) {
|
||||
return this.showReplies
|
||||
} else if (toot.reblog) {
|
||||
|
@ -95,11 +133,13 @@ export default {
|
|||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
const previousFocusedId = this.focusedId
|
||||
|
@ -117,18 +157,32 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
|
||||
if (
|
||||
this.loadingMore ||
|
||||
(this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling)
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline && this.heading) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadHomeTimeline',
|
||||
false
|
||||
)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
this.scrollPosition.prepare()
|
||||
|
@ -141,8 +195,13 @@ export default {
|
|||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true)
|
||||
this.$store.commit('TimelineSpace/Contents/Home/archiveTimeline')
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -165,7 +224,7 @@ export default {
|
|||
if (this.heading && newState.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Home/saveMarker')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
|
@ -179,26 +238,36 @@ export default {
|
|||
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Home/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
|
||||
.then(statuses => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Home/lazyFetchTimeline',
|
||||
this.timeline[this.timeline.length - 1]
|
||||
)
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Home/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Home/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -213,7 +282,10 @@ export default {
|
|||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Home/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
|
@ -225,11 +297,13 @@ export default {
|
|||
},
|
||||
fetchTimelineSince(since_id) {
|
||||
this.loadingMore = true
|
||||
this.$store.dispatch('TimelineSpace/Contents/Home/fetchTimelineSince', since_id).finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Home/fetchTimelineSince', since_id)
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
async reload() {
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
|
@ -244,19 +318,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -277,8 +359,8 @@ export default {
|
|||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Home/changeScrolling', false)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -315,4 +397,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<template v-for="account in members">
|
||||
<user :user="account" :remove="true" @removeAccount="removeAccount"></user>
|
||||
<user
|
||||
:user="account"
|
||||
:remove="true"
|
||||
@removeAccount="removeAccount"
|
||||
></user>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -21,8 +25,8 @@ export default {
|
|||
components: { User },
|
||||
computed: {
|
||||
...mapState({
|
||||
members: state => state.TimelineSpace.Contents.Lists.Edit.members
|
||||
})
|
||||
members: (state) => state.TimelineSpace.Contents.Lists.Edit.members,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
|
@ -31,11 +35,14 @@ export default {
|
|||
async init() {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Edit/fetchMembers', this.list_id)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Edit/fetchMembers',
|
||||
this.list_id
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.members_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
|
@ -44,25 +51,37 @@ export default {
|
|||
async removeAccount(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Edit/removeAccount', {
|
||||
account: account,
|
||||
listId: this.list_id
|
||||
})
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Edit/fetchMembers', this.list_id)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Edit/removeAccount',
|
||||
{
|
||||
account: account,
|
||||
listId: this.list_id,
|
||||
}
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Edit/fetchMembers',
|
||||
this.list_id
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.remove_user_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
}
|
||||
},
|
||||
addAccount() {
|
||||
this.$store.commit('TimelineSpace/Modals/AddListMember/setListId', this.list_id)
|
||||
this.$store.dispatch('TimelineSpace/Modals/AddListMember/changeModal', true)
|
||||
}
|
||||
}
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/AddListMember/setListId',
|
||||
this.list_id
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/AddListMember/changeModal',
|
||||
true
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<template>
|
||||
<div id="lists">
|
||||
<div class="new-list" v-loading="creating" :element-loading-background="loadingBackground">
|
||||
<div
|
||||
class="new-list"
|
||||
v-loading="creating"
|
||||
:element-loading-background="loadingBackground"
|
||||
>
|
||||
<el-form :inline="true">
|
||||
<input v-model="title" :placeholder="$t('lists.index.new_list')" class="list-title" />
|
||||
<input
|
||||
v-model="title"
|
||||
:placeholder="$t('lists.index.new_list')"
|
||||
class="list-title"
|
||||
/>
|
||||
<el-button type="text" class="create" @click="createList">
|
||||
<font-awesome-icon icon="plus" />
|
||||
</el-button>
|
||||
|
@ -32,14 +40,14 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
title: '',
|
||||
creating: false
|
||||
creating: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
lists: state => state.TimelineSpace.Contents.Lists.Index.lists,
|
||||
loadingBackground: state => state.App.theme.wrapper_mask_color
|
||||
})
|
||||
lists: (state) => state.TimelineSpace.Contents.Lists.Index.lists,
|
||||
loadingBackground: (state) => state.App.theme.wrapper_mask_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
|
@ -52,22 +60,29 @@ export default {
|
|||
return this.$route.params.id
|
||||
},
|
||||
fetch() {
|
||||
return this.$store.dispatch('TimelineSpace/Contents/Lists/Index/fetchLists').catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.lists_fetch_error'),
|
||||
type: 'error'
|
||||
return this.$store
|
||||
.dispatch('TimelineSpace/Contents/Lists/Index/fetchLists')
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.lists_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
async createList() {
|
||||
this.creating = true
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Index/createList', this.title)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Index/fetchLists')
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Index/createList',
|
||||
this.title
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Index/fetchLists'
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.list_create_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.creating = false
|
||||
|
@ -78,17 +93,24 @@ export default {
|
|||
return this.$router.push(`/${this.id()}/lists/${list.id}/edit`)
|
||||
},
|
||||
del(list) {
|
||||
this.$confirm(this.$t('lists.index.delete.confirm.message'), this.$t('lists.index.delete.confirm.title'), {
|
||||
confirmButtonText: this.$t('lists.index.delete.confirm.ok'),
|
||||
cancelButtonText: this.$t('lists.index.delete.confirm.cancel'),
|
||||
type: 'warning'
|
||||
})
|
||||
this.$confirm(
|
||||
this.$t('lists.index.delete.confirm.message'),
|
||||
this.$t('lists.index.delete.confirm.title'),
|
||||
{
|
||||
confirmButtonText: this.$t('lists.index.delete.confirm.ok'),
|
||||
cancelButtonText: this.$t('lists.index.delete.confirm.cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Lists/Index/deleteList', list)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Index/deleteList',
|
||||
list
|
||||
)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,9 +1,29 @@
|
|||
<template>
|
||||
<div name="list" class="list-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
name="list"
|
||||
class="list-timeline"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -21,13 +41,18 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -36,28 +61,30 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'list',
|
||||
props: ['list_id'],
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
scrollPosition: null,
|
||||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null
|
||||
resizeTime: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'list',
|
||||
props: ['list_id'],
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
timeline: state => state.TimelineSpace.Contents.Lists.Show.timeline,
|
||||
lazyLoading: state => state.TimelineSpace.Contents.Lists.Show.lazyLoading,
|
||||
heading: state => state.TimelineSpace.Contents.Lists.Show.heading,
|
||||
scrolling: state => state.TimelineSpace.Contents.Lists.Show.scrolling
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
timeline: (state) => state.TimelineSpace.Contents.Lists.Show.timeline,
|
||||
lazyLoading: (state) =>
|
||||
state.TimelineSpace.Contents.Lists.Show.lazyLoading,
|
||||
heading: (state) => state.TimelineSpace.Contents.Lists.Show.heading,
|
||||
scrolling: (state) => state.TimelineSpace.Contents.Lists.Show.scrolling,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
|
@ -68,9 +95,11 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
|
@ -79,7 +108,9 @@ export default {
|
|||
})
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
const previousFocusedId = this.focusedId
|
||||
|
@ -93,13 +124,20 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
|
||||
if (
|
||||
this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
|
@ -123,11 +161,17 @@ export default {
|
|||
},
|
||||
focusedId: function (newState, _oldState) {
|
||||
if (newState && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
|
||||
|
@ -137,35 +181,56 @@ export default {
|
|||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/archiveTimeline')
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/clearTimeline')
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async load() {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/stopStreaming'
|
||||
)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/fetchTimeline', this.list_id)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/fetchTimeline',
|
||||
this.list_id
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/startStreaming', this.list_id).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/startStreaming',
|
||||
this.list_id
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
return 'started'
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/deleteToot', message.id)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/deleteToot',
|
||||
message.id
|
||||
)
|
||||
},
|
||||
onScroll(event) {
|
||||
if (moment().diff(this.resizeTime) < 500) {
|
||||
|
@ -173,48 +238,67 @@ export default {
|
|||
}
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Lists/Show/lazyFetchTimeline', {
|
||||
list_id: this.list_id,
|
||||
status: this.timeline[this.timeline.length - 1]
|
||||
status: this.timeline[this.timeline.length - 1],
|
||||
})
|
||||
.then(statuses => {
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (event.target.scrollTop <= 10 && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
|
@ -222,19 +306,31 @@ export default {
|
|||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
try {
|
||||
await this.reloadable()
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/stopStreaming')
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Lists/Show/fetchTimeline', this.list_id).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/stopStreaming'
|
||||
)
|
||||
await this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/fetchTimeline',
|
||||
this.list_id
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$store.dispatch('TimelineSpace/Contents/Lists/Show/startStreaming', this.list_id).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Show/startStreaming',
|
||||
this.list_id
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.start_streaming_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/changeLoading', false)
|
||||
}
|
||||
|
@ -244,19 +340,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -273,12 +377,18 @@ export default {
|
|||
}
|
||||
},
|
||||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Lists/Show/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Lists/Show/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -306,4 +416,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<template>
|
||||
<div id="local" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="local"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -21,13 +40,18 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -36,30 +60,31 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'local',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
scrollPosition: null,
|
||||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null
|
||||
resizeTime: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'local',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/Local', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
scrolling: state => state.scrolling
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: state => state.TimelineSpace.unreadNotification
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: (state) => state.TimelineSpace.unreadNotification,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
|
@ -70,16 +95,23 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadLocalTimeline', false)
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadLocalTimeline',
|
||||
false
|
||||
)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
if (!this.unreadNotification.local) {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
await this.initialize().finally(_ => {
|
||||
await this.initialize().finally((_) => {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
})
|
||||
}
|
||||
|
@ -97,18 +129,31 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
|
||||
if (
|
||||
this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadLocalTimeline && this.heading) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadLocalTimeline', false)
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadLocalTimeline &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadLocalTimeline',
|
||||
false
|
||||
)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
this.scrollPosition.prepare()
|
||||
|
@ -128,8 +173,13 @@ export default {
|
|||
if (!this.unreadNotification.local) {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/clearTimeline')
|
||||
}
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -147,16 +197,18 @@ export default {
|
|||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeHeading', true)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async initialize() {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Local/fetchLocalTimeline').catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/Local/fetchLocalTimeline')
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
await this.$store.dispatch('TimelineSpace/bindLocalStreaming')
|
||||
this.$store.dispatch('TimelineSpace/startLocalStreaming')
|
||||
},
|
||||
|
@ -176,26 +228,36 @@ export default {
|
|||
}
|
||||
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Local/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
|
||||
.then(statuses => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Local/lazyFetchTimeline',
|
||||
this.timeline[this.timeline.length - 1]
|
||||
)
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Local/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Local/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -209,7 +271,10 @@ export default {
|
|||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Local/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
|
@ -226,19 +291,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -257,10 +330,13 @@ export default {
|
|||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', true)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Local/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Local/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -296,4 +372,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,15 +1,45 @@
|
|||
<template>
|
||||
<div id="mentions" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="mentions" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="mentions"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="mentions"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<template v-if="item.id === 'loading-card'">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
|
||||
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchMentionsSince" />
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.id]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<StatusLoading
|
||||
:since_id="item.since_id"
|
||||
:max_id="item.max_id"
|
||||
:loading="loadingMore"
|
||||
@load_since="fetchMentionsSince"
|
||||
/>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.url]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.url]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<notification
|
||||
:message="item"
|
||||
:focused="item.id === focusedId"
|
||||
|
@ -27,13 +57,18 @@
|
|||
</template>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Notification from '~/src/renderer/components/organisms/Notification'
|
||||
|
@ -43,9 +78,6 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'mentions',
|
||||
components: { Notification, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
|
@ -53,23 +85,27 @@ export default {
|
|||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null,
|
||||
loadingMore: false
|
||||
loadingMore: false,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'mentions',
|
||||
components: { Notification, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
...mapState('TimelineSpace/HeaderMenu', {
|
||||
startReload: state => state.reload
|
||||
startReload: (state) => state.reload,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/SideBar', {
|
||||
openSideBar: state => state.openSideBar
|
||||
openSideBar: (state) => state.openSideBar,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/Mentions', {
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
scrolling: state => state.scrolling
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
...mapGetters('TimelineSpace/Contents/Mentions', ['mentions']),
|
||||
|
@ -81,13 +117,17 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
|
||||
const currentIndex = this.mentions.findIndex(
|
||||
(toot) => this.focusedId === toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadMentions', false)
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
const previousFocusedId = this.focusedId
|
||||
|
@ -105,17 +145,28 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
|
||||
if (
|
||||
this.loadingMore ||
|
||||
(this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling)
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadMentions && this.heading) {
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadMentions &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadMentions', false)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
|
@ -129,8 +180,13 @@ export default {
|
|||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/archiveMentions')
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -144,16 +200,22 @@ export default {
|
|||
},
|
||||
focusedId: function (newState, _oldState) {
|
||||
if (newState && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeHeading',
|
||||
true
|
||||
)
|
||||
}
|
||||
},
|
||||
mentions: function (newState, _oldState) {
|
||||
if (this.heading && newState.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Mentions/saveMarker')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
|
@ -162,39 +224,58 @@ export default {
|
|||
}
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Mentions/lazyFetchMentions', this.mentions[this.mentions.length - 1])
|
||||
.then(statuses => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Mentions/lazyFetchMentions',
|
||||
this.mentions[this.mentions.length - 1]
|
||||
)
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (event.target.scrollTop <= 10 && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Contents/Mentions/saveMarker')
|
||||
}
|
||||
|
||||
|
@ -202,17 +283,25 @@ export default {
|
|||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
fetchMentionsSince(since_id) {
|
||||
this.loadingMore = true
|
||||
this.$store.dispatch('TimelineSpace/Contents/Mentions/fetchMentionsSince', since_id).finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Mentions/fetchMentionsSince',
|
||||
since_id
|
||||
)
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
async reload() {
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
|
@ -230,7 +319,9 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
|
||||
const currentIndex = this.mentions.findIndex(
|
||||
(toot) => this.focusedId === toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.mentions[0].id
|
||||
} else if (currentIndex < this.mentions.length) {
|
||||
|
@ -238,7 +329,9 @@ export default {
|
|||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.mentions.findIndex(toot => this.focusedId === toot.id)
|
||||
const currentIndex = this.mentions.findIndex(
|
||||
(toot) => this.focusedId === toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
|
@ -259,12 +352,18 @@ export default {
|
|||
}
|
||||
},
|
||||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Mentions/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Mentions/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -300,4 +399,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,15 +1,45 @@
|
|||
<template>
|
||||
<div id="notifications" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="handledNotifications" :min-item-size="20" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="notifications"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="handledNotifications"
|
||||
:min-item-size="20"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<template v-if="item.id === 'loading-card'">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.id]" :data-index="index" :watchData="true">
|
||||
<StatusLoading :since_id="item.since_id" :max_id="item.max_id" :loading="loadingMore" @load_since="fetchNotificationsSince" />
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.id]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<StatusLoading
|
||||
:since_id="item.since_id"
|
||||
:max_id="item.max_id"
|
||||
:loading="loadingMore"
|
||||
@load_since="fetchNotificationsSince"
|
||||
/>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.url]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.url]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<notification
|
||||
:message="item"
|
||||
:focused="item.id === focusedId"
|
||||
|
@ -26,13 +56,18 @@
|
|||
</template>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Notification from '~/src/renderer/components/organisms/Notification'
|
||||
|
@ -42,9 +77,6 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'notifications',
|
||||
components: { Notification, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
|
@ -52,22 +84,29 @@ export default {
|
|||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null,
|
||||
loadingMore: false
|
||||
loadingMore: false,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'notifications',
|
||||
components: { Notification, StatusLoading },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/Notifications', {
|
||||
notifications: state => state.notifications,
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
scrolling: state => state.scrolling
|
||||
notifications: (state) => state.notifications,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Contents/Notifications', ['handledNotifications', 'filters']),
|
||||
...mapGetters('TimelineSpace/Contents/Notifications', [
|
||||
'handledNotifications',
|
||||
'filters',
|
||||
]),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
shortcutEnabled: function () {
|
||||
if (this.modalOpened) {
|
||||
|
@ -77,14 +116,21 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes notifications are deleted, so perhaps focused notification don't exist.
|
||||
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
|
||||
const currentIndex = this.handledNotifications.findIndex(
|
||||
(notification) => this.focusedId === notification.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadNotifications', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadNotifications',
|
||||
false
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
|
||||
Event.$on('focus-timeline', () => {
|
||||
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
|
||||
|
@ -103,18 +149,32 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.loadingMore || (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling)) {
|
||||
if (
|
||||
this.loadingMore ||
|
||||
(this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling)
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadNotifications && this.heading) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadNotifications', false)
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadNotifications &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadNotifications',
|
||||
false
|
||||
)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
this.scrollPosition.prepare()
|
||||
|
@ -125,10 +185,20 @@ export default {
|
|||
this.observer.disconnect()
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/archiveNotifications')
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/archiveNotifications'
|
||||
)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -142,9 +212,15 @@ export default {
|
|||
},
|
||||
focusedId: function (newState, _oldState) {
|
||||
if (newState >= 0 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
|
||||
}
|
||||
},
|
||||
|
@ -152,7 +228,7 @@ export default {
|
|||
if (this.heading && newState.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
|
@ -161,11 +237,15 @@ export default {
|
|||
}
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
|
@ -173,29 +253,41 @@ export default {
|
|||
'TimelineSpace/Contents/Notifications/lazyFetchNotifications',
|
||||
this.handledNotifications[this.handledNotifications.length - 1]
|
||||
)
|
||||
.then(statuses => {
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.notification_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (event.target.scrollTop > 10 && this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeHeading',
|
||||
false
|
||||
)
|
||||
} else if (event.target.scrollTop <= 10 && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeHeading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeHeading',
|
||||
true
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker')
|
||||
}
|
||||
|
@ -204,17 +296,25 @@ export default {
|
|||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
fetchNotificationsSince(since_id) {
|
||||
this.loadingMore = true
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/fetchNotificationsSince', since_id).finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Notifications/fetchNotificationsSince',
|
||||
since_id
|
||||
)
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
this.loadingMore = false
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
async reload() {
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
|
@ -226,14 +326,19 @@ export default {
|
|||
}
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/Notifications/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Notifications/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
upper() {
|
||||
this.$refs.scroller.scrollToItem(0)
|
||||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
|
||||
const currentIndex = this.handledNotifications.findIndex(
|
||||
(notification) => this.focusedId === notification.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.handledNotifications[0].id
|
||||
} else if (currentIndex < this.handledNotifications.length) {
|
||||
|
@ -241,7 +346,9 @@ export default {
|
|||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.handledNotifications.findIndex(notification => this.focusedId === notification.id)
|
||||
const currentIndex = this.handledNotifications.findIndex(
|
||||
(notification) => this.focusedId === notification.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
|
@ -260,8 +367,8 @@ export default {
|
|||
this.focusedId = this.handledNotifications[0].id
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -297,4 +404,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<template>
|
||||
<div id="public" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
|
||||
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
|
||||
<DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
|
||||
<div
|
||||
id="public"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div
|
||||
v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }"
|
||||
@shortkey="reload()"
|
||||
></div>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="86"
|
||||
id="scroller"
|
||||
class="scroller"
|
||||
ref="scroller"
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:focused="item.uri + item.id === focusedId"
|
||||
|
@ -21,13 +40,18 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
|
||||
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
|
||||
<div
|
||||
:class="openSideBar ? 'upper-with-side-bar' : 'upper'"
|
||||
v-show="!heading"
|
||||
>
|
||||
<el-button type="primary" :icon="ElIconArrowUp" @click="upper" circle>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowUp as ElIconArrowUp } from '@element-plus/icons'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import Toot from '~/src/renderer/components/organisms/Toot'
|
||||
|
@ -36,30 +60,32 @@ import { Event } from '~/src/renderer/components/event'
|
|||
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
|
||||
|
||||
export default {
|
||||
name: 'public',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
data() {
|
||||
return {
|
||||
focusedId: null,
|
||||
scrollPosition: null,
|
||||
observer: null,
|
||||
scrollTime: null,
|
||||
resizeTime: null
|
||||
resizeTime: null,
|
||||
ElIconArrowUp,
|
||||
}
|
||||
},
|
||||
name: 'public',
|
||||
components: { Toot },
|
||||
mixins: [reloadable],
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/Public', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
scrolling: state => state.scrolling
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
heading: (state) => state.heading,
|
||||
scrolling: (state) => state.scrolling,
|
||||
}),
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: state => state.TimelineSpace.timelineSetting.unreadNotification
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
startReload: (state) => state.TimelineSpace.HeaderMenu.reload,
|
||||
unreadNotification: (state) =>
|
||||
state.TimelineSpace.timelineSetting.unreadNotification,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Contents/Public', ['filters']),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
|
@ -71,16 +97,23 @@ export default {
|
|||
return true
|
||||
}
|
||||
// Sometimes toots are deleted, so perhaps focused toot don't exist.
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
return currentIndex === -1
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadPublicTimeline', false)
|
||||
document.getElementById('scroller').addEventListener('scroll', this.onScroll)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadPublicTimeline',
|
||||
false
|
||||
)
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
if (!this.unreadNotification.public) {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', true)
|
||||
await this.initialize().finally(_ => {
|
||||
await this.initialize().finally((_) => {
|
||||
this.$store.commit('TimelineSpace/Contents/changeLoading', false)
|
||||
})
|
||||
}
|
||||
|
@ -98,18 +131,31 @@ export default {
|
|||
this.scrollPosition.prepare()
|
||||
|
||||
this.observer = new ResizeObserver(() => {
|
||||
if (this.scrollPosition && !this.heading && !this.lazyLoading && !this.scrolling) {
|
||||
if (
|
||||
this.scrollPosition &&
|
||||
!this.heading &&
|
||||
!this.lazyLoading &&
|
||||
!this.scrolling
|
||||
) {
|
||||
this.resizeTime = moment()
|
||||
this.scrollPosition.restore()
|
||||
}
|
||||
})
|
||||
|
||||
const scrollWrapper = el.getElementsByClassName('vue-recycle-scroller__item-wrapper')[0]
|
||||
const scrollWrapper = el.getElementsByClassName(
|
||||
'vue-recycle-scroller__item-wrapper'
|
||||
)[0]
|
||||
this.observer.observe(scrollWrapper)
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadPublicTimeline && this.heading) {
|
||||
this.$store.commit('TimelineSpace/SideMenu/changeUnreadPublicTimeline', false)
|
||||
if (
|
||||
this.$store.state.TimelineSpace.SideMenu.unreadPublicTimeline &&
|
||||
this.heading
|
||||
) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/SideMenu/changeUnreadPublicTimeline',
|
||||
false
|
||||
)
|
||||
}
|
||||
if (this.scrollPosition) {
|
||||
this.scrollPosition.prepare()
|
||||
|
@ -129,8 +175,13 @@ export default {
|
|||
if (!this.unreadNotification.public) {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/clearTimeline')
|
||||
}
|
||||
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
|
||||
document.getElementById('scroller').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('scroller') !== undefined &&
|
||||
document.getElementById('scroller') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('scroller')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
document.getElementById('scroller').scrollTop = 0
|
||||
}
|
||||
},
|
||||
|
@ -148,16 +199,18 @@ export default {
|
|||
} else if (newState === null && !this.heading) {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeHeading', true)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async initialize() {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/Public/fetchPublicTimeline').catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
await this.$store
|
||||
.dispatch('TimelineSpace/Contents/Public/fetchPublicTimeline')
|
||||
.catch((_) => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
await this.$store.dispatch('TimelineSpace/bindPublicStreaming')
|
||||
this.$store.dispatch('TimelineSpace/startPublicStreaming')
|
||||
},
|
||||
|
@ -174,30 +227,43 @@ export default {
|
|||
|
||||
this.scrollTime = moment()
|
||||
if (!this.scrolling) {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Public/changeScrolling',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('scroller').scrollHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('scroller').scrollHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Public/lazyFetchTimeline', this.timeline[this.timeline.length - 1])
|
||||
.then(statuses => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Public/lazyFetchTimeline',
|
||||
this.timeline[this.timeline.length - 1]
|
||||
)
|
||||
.then((statuses) => {
|
||||
if (statuses === null) {
|
||||
return
|
||||
}
|
||||
if (statuses.length > 0) {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Public/changeScrolling',
|
||||
true
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Public/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -212,7 +278,10 @@ export default {
|
|||
const now = moment()
|
||||
if (now.diff(this.scrollTime) >= 150) {
|
||||
this.scrollTime = null
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Public/changeScrolling',
|
||||
false
|
||||
)
|
||||
}
|
||||
}, 150)
|
||||
},
|
||||
|
@ -229,19 +298,27 @@ export default {
|
|||
this.focusedId = null
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === 0) {
|
||||
this.focusedId = null
|
||||
} else if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -260,10 +337,13 @@ export default {
|
|||
sizeChanged() {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', true)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('TimelineSpace/Contents/Public/changeScrolling', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Public/changeScrolling',
|
||||
false
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -299,4 +379,5 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" src="@/assets/timeline-transition.scss"></style>
|
||||
|
|
|
@ -2,8 +2,18 @@
|
|||
<div id="search">
|
||||
<div class="search-header">
|
||||
<el-form :inline="true">
|
||||
<el-select v-model="target" :placeholder="$t('search.search')" class="search-target">
|
||||
<el-option v-for="item in searchTargets" :key="item.target" :label="item.label" :value="item.target"> </el-option>
|
||||
<el-select
|
||||
v-model="target"
|
||||
:placeholder="$t('search.search')"
|
||||
class="search-target"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in searchTargets"
|
||||
:key="item.target"
|
||||
:label="item.label"
|
||||
:value="item.target"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<input
|
||||
v-model="query"
|
||||
|
@ -35,7 +45,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
target: 'account',
|
||||
query: ''
|
||||
query: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -44,52 +54,64 @@ export default {
|
|||
return [
|
||||
{
|
||||
target: 'account',
|
||||
label: this.$t('search.account')
|
||||
label: this.$t('search.account'),
|
||||
},
|
||||
{
|
||||
target: 'tag',
|
||||
label: this.$t('search.tag')
|
||||
label: this.$t('search.tag'),
|
||||
},
|
||||
{
|
||||
target: 'toot',
|
||||
label: this.$t('search.toot')
|
||||
}
|
||||
label: this.$t('search.toot'),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
search() {
|
||||
switch (this.target) {
|
||||
case 'account':
|
||||
this.$store.dispatch('TimelineSpace/Contents/Search/Account/search', this.query).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Search/Account/search',
|
||||
this.query
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
break
|
||||
case 'tag':
|
||||
this.$store.dispatch('TimelineSpace/Contents/Search/Tag/search', `#${this.query}`).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/Search/Tag/search',
|
||||
`#${this.query}`
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
break
|
||||
case 'toot':
|
||||
this.$store.dispatch('TimelineSpace/Contents/Search/Toots/search', this.query).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/Search/Toots/search', this.query)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.search_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
<template>
|
||||
<div id="search_account">
|
||||
<DynamicScroller :items="results" :min-item-size="20" class="scroller" page-mode>
|
||||
<DynamicScroller
|
||||
:items="results"
|
||||
:min-item-size="20"
|
||||
class="scroller"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.acct]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.acct]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<user :user="item"></user>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
|
@ -19,13 +30,14 @@ export default {
|
|||
components: { User },
|
||||
computed: {
|
||||
...mapState({
|
||||
results: state => state.TimelineSpace.Contents.Search.Account.results
|
||||
})
|
||||
results: (state) => state.TimelineSpace.Contents.Search.Account.results,
|
||||
}),
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Search/Account/updateResults', [])
|
||||
}
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Search/Account/updateResults',
|
||||
[]
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
<template>
|
||||
<div id="search_tag">
|
||||
<DynamicScroller :items="results" :min-item-size="46" key-field="name" class="scroller" page-mode>
|
||||
<DynamicScroller
|
||||
:items="results"
|
||||
:min-item-size="46"
|
||||
key-field="name"
|
||||
class="scroller"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.name]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.name]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<tag :tag="item"></tag>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
|
@ -19,11 +31,11 @@ export default {
|
|||
components: { Tag },
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/Search/Tag', {
|
||||
results: state => state.results
|
||||
})
|
||||
results: (state) => state.results,
|
||||
}),
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Search/Tag/updateResults', [])
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
<template>
|
||||
<div id="search_account">
|
||||
<DynamicScroller :items="results" :min-item-size="60" class="scroller" page-mode>
|
||||
<DynamicScroller
|
||||
:items="results"
|
||||
:min-item-size="60"
|
||||
class="scroller"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot :message="item"></toot>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
|
@ -19,13 +30,11 @@ export default {
|
|||
components: { Toot },
|
||||
computed: {
|
||||
...mapState({
|
||||
results: state => state.TimelineSpace.Contents.Search.Toots.results
|
||||
})
|
||||
results: (state) => state.TimelineSpace.Contents.Search.Toots.results,
|
||||
}),
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit('TimelineSpace/Contents/Search/Toots/updateResults', [])
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
<template>
|
||||
<div class="side-bar" v-if="openSideBar" v-shortkey="shortcutEnabled ? { close: ['esc'] } : {}" @shortkey="handleKey">
|
||||
<div
|
||||
class="side-bar"
|
||||
v-if="openSideBar"
|
||||
v-shortkey="shortcutEnabled ? { close: ['esc'] } : {}"
|
||||
@shortkey="handleKey"
|
||||
>
|
||||
<div class="header">
|
||||
<i class="el-icon-loading" v-show="loading"></i>
|
||||
<i class="el-icon-refresh" @click="reload"></i>
|
||||
<i class="el-icon-close" @click="close"></i>
|
||||
<el-icon><el-icon-loading /></el-icon>
|
||||
<el-icon><el-icon-refresh /></el-icon>
|
||||
<el-icon><el-icon-close /></el-icon>
|
||||
</div>
|
||||
<div id="sidebar_scrollable">
|
||||
<account-profile v-if="component === 1" v-on:change-loading="changeLoading"></account-profile>
|
||||
<account-profile
|
||||
v-if="component === 1"
|
||||
v-on:change-loading="changeLoading"
|
||||
></account-profile>
|
||||
<toot-detail v-else-if="component === 2"></toot-detail>
|
||||
<div
|
||||
class="loading"
|
||||
|
@ -21,36 +29,44 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
Loading as ElIconLoading,
|
||||
Refresh as ElIconRefresh,
|
||||
Close as ElIconClose,
|
||||
} from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
import TootDetail from './SideBar/TootDetail'
|
||||
import AccountProfile from './SideBar/AccountProfile'
|
||||
|
||||
export default {
|
||||
name: 'side-bar',
|
||||
components: {
|
||||
TootDetail,
|
||||
AccountProfile
|
||||
AccountProfile,
|
||||
ElIconLoading,
|
||||
ElIconRefresh,
|
||||
ElIconClose,
|
||||
},
|
||||
name: 'side-bar',
|
||||
props: {
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
component: state => state.TimelineSpace.Contents.SideBar.component,
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
openSideBar: (state) => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
component: (state) => state.TimelineSpace.Contents.SideBar.component,
|
||||
backgroundColor: (state) => state.App.theme.background_color,
|
||||
}),
|
||||
shortcutEnabled: function() {
|
||||
shortcutEnabled: function () {
|
||||
return !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.close()
|
||||
|
@ -71,8 +87,8 @@ export default {
|
|||
this.close()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -8,14 +8,30 @@
|
|||
role="article"
|
||||
aria-label="account profile"
|
||||
>
|
||||
<div class="header-background" v-bind:style="{ backgroundImage: 'url(' + account.header + ')' }">
|
||||
<div
|
||||
class="header-background"
|
||||
v-bind:style="{ backgroundImage: 'url(' + account.header + ')' }"
|
||||
>
|
||||
<div class="header">
|
||||
<div class="relationship" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||
<div
|
||||
class="relationship"
|
||||
v-if="relationship !== null && relationship !== '' && !isOwnProfile"
|
||||
>
|
||||
<div class="follower-status">
|
||||
<el-tag class="status" size="small" v-if="relationship.followed_by">{{ $t('side_bar.account_profile.follows_you') }}</el-tag>
|
||||
<el-tag class="status" size="medium" v-else>{{ $t('side_bar.account_profile.doesnt_follow_you') }}</el-tag>
|
||||
<el-tag
|
||||
class="status"
|
||||
size="small"
|
||||
v-if="relationship.followed_by"
|
||||
>{{ $t('side_bar.account_profile.follows_you') }}</el-tag
|
||||
>
|
||||
<el-tag class="status" size="medium" v-else>{{
|
||||
$t('side_bar.account_profile.doesnt_follow_you')
|
||||
}}</el-tag>
|
||||
</div>
|
||||
<div class="notify" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||
<div
|
||||
class="notify"
|
||||
v-if="relationship !== null && relationship !== '' && !isOwnProfile"
|
||||
>
|
||||
<div
|
||||
v-if="relationship.notifying"
|
||||
class="unsubscribe"
|
||||
|
@ -24,15 +40,27 @@
|
|||
>
|
||||
<font-awesome-icon icon="bell" size="xl" />
|
||||
</div>
|
||||
<div v-else class="subscribe" @click="subscribe(account)" :title="$t('side_bar.account_profile.subscribe')">
|
||||
<div
|
||||
v-else
|
||||
class="subscribe"
|
||||
@click="subscribe(account)"
|
||||
:title="$t('side_bar.account_profile.subscribe')"
|
||||
>
|
||||
<font-awesome-icon :icon="['far', 'bell']" size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-info">
|
||||
<div class="more" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||
<popper trigger="click" :options="{ placement: 'bottom' }" ref="popper">
|
||||
<div
|
||||
class="more"
|
||||
v-if="relationship !== null && relationship !== '' && !isOwnProfile"
|
||||
>
|
||||
<popper
|
||||
trigger="click"
|
||||
:options="{ placement: 'bottom' }"
|
||||
ref="popper"
|
||||
>
|
||||
<div class="popper">
|
||||
<ul class="menu-list">
|
||||
<li role="button" @click="openBrowser(account)">
|
||||
|
@ -56,22 +84,45 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<el-button slot="reference" type="text" :title="$t('side_bar.account_profile.detail')">
|
||||
<el-button
|
||||
slot="reference"
|
||||
type="text"
|
||||
:title="$t('side_bar.account_profile.detail')"
|
||||
>
|
||||
<font-awesome-icon icon="gear" size="xl" />
|
||||
</el-button>
|
||||
</popper>
|
||||
</div>
|
||||
<div class="icon" role="presentation">
|
||||
<FailoverImg :src="account.avatar" :alt="`Avatar of ${account.username}`" />
|
||||
<FailoverImg
|
||||
:src="account.avatar"
|
||||
:alt="`Avatar of ${account.username}`"
|
||||
/>
|
||||
</div>
|
||||
<div class="follow-status" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||
<div v-if="relationship.following" class="unfollow" @click="unfollow(account)" :title="$t('side_bar.account_profile.unfollow')">
|
||||
<div
|
||||
class="follow-status"
|
||||
v-if="relationship !== null && relationship !== '' && !isOwnProfile"
|
||||
>
|
||||
<div
|
||||
v-if="relationship.following"
|
||||
class="unfollow"
|
||||
@click="unfollow(account)"
|
||||
:title="$t('side_bar.account_profile.unfollow')"
|
||||
>
|
||||
<font-awesome-icon icon="user-xmark" size="xl" />
|
||||
</div>
|
||||
<div v-else-if="relationship.requested" :title="$t('side_bar.account_profile.follow_requested')">
|
||||
<div
|
||||
v-else-if="relationship.requested"
|
||||
:title="$t('side_bar.account_profile.follow_requested')"
|
||||
>
|
||||
<font-awesome-icon icon="hourglass" size="xl" />
|
||||
</div>
|
||||
<div v-else class="follow" @click="follow(account)" :title="$t('side_bar.account_profile.follow')">
|
||||
<div
|
||||
v-else
|
||||
class="follow"
|
||||
@click="follow(account)"
|
||||
:title="$t('side_bar.account_profile.follow')"
|
||||
>
|
||||
<font-awesome-icon icon="user-plus" size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -80,7 +131,11 @@
|
|||
<bdi v-html="username(account)"></bdi>
|
||||
</div>
|
||||
<div class="account">@{{ account.acct }}</div>
|
||||
<div class="note" v-html="note(account)" @click.capture.prevent="noteClick"></div>
|
||||
<div
|
||||
class="note"
|
||||
v-html="note(account)"
|
||||
@click.capture.prevent="noteClick"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="identity">
|
||||
|
@ -88,7 +143,9 @@
|
|||
<dt>
|
||||
{{ identity.provider }}
|
||||
</dt>
|
||||
<dd @click.capture.prevent="identityOpen(identity.profile_url)">{{ identity.provider_username }}</dd>
|
||||
<dd @click.capture.prevent="identityOpen(identity.profile_url)">
|
||||
{{ identity.provider_username }}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="metadata">
|
||||
|
@ -100,7 +157,11 @@
|
|||
</dl>
|
||||
</div>
|
||||
<el-row class="basic-info">
|
||||
<el-col :span="8" :class="activeTab === 1 ? 'info info-active' : 'info'" @click="changeTab">
|
||||
<el-col
|
||||
:span="8"
|
||||
:class="activeTab === 1 ? 'info info-active' : 'info'"
|
||||
@click="changeTab"
|
||||
>
|
||||
<el-button type="text" class="tab" @click="changeTab(1)">
|
||||
<div class="title">{{ $t('side_bar.account_profile.toots') }}</div>
|
||||
<div class="count">{{ account.statuses_count }}</div>
|
||||
|
@ -114,7 +175,9 @@
|
|||
</el-col>
|
||||
<el-col :span="8" :class="activeTab === 3 ? 'info info-active' : 'info'">
|
||||
<el-button type="text" class="tab" @click="changeTab(3)">
|
||||
<div class="title">{{ $t('side_bar.account_profile.followers') }}</div>
|
||||
<div class="title">
|
||||
{{ $t('side_bar.account_profile.followers') }}
|
||||
</div>
|
||||
<div class="count">{{ account.followers_count }}</div>
|
||||
</el-button>
|
||||
</el-col>
|
||||
|
@ -142,32 +205,34 @@ export default {
|
|||
Timeline,
|
||||
Follows,
|
||||
Followers,
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: 1
|
||||
activeTab: 1,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
theme: state => {
|
||||
theme: (state) => {
|
||||
return {
|
||||
'--theme-mask-color': state.App.theme.wrapper_mask_color,
|
||||
'--theme-border-color': state.App.theme.border_color,
|
||||
'--theme-primary-color': state.App.theme.primary_color
|
||||
'--theme-primary-color': state.App.theme.primary_color,
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile', {
|
||||
account: state => state.account,
|
||||
identityProofs: state => state.identityProofs,
|
||||
relationship: state => state.relationship,
|
||||
loading: state => state.loading,
|
||||
muting: state => state.relationship && state.relationship.muting,
|
||||
blocking: state => state.relationship && state.relationship.blocking
|
||||
account: (state) => state.account,
|
||||
identityProofs: (state) => state.identityProofs,
|
||||
relationship: (state) => state.relationship,
|
||||
loading: (state) => state.loading,
|
||||
muting: (state) => state.relationship && state.relationship.muting,
|
||||
blocking: (state) => state.relationship && state.relationship.blocking,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile', ['isOwnProfile'])
|
||||
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile', [
|
||||
'isOwnProfile',
|
||||
]),
|
||||
},
|
||||
watch: {
|
||||
account: function () {
|
||||
|
@ -175,7 +240,7 @@ export default {
|
|||
},
|
||||
loading: function (newState, _oldState) {
|
||||
this.$emit('change-loading', newState)
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -195,29 +260,47 @@ export default {
|
|||
}
|
||||
},
|
||||
follow(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/follow',
|
||||
account
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
unfollow(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unfollow',
|
||||
account
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.unfollow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
changeTab(index) {
|
||||
|
@ -228,25 +311,43 @@ export default {
|
|||
this.$refs.popper.doClose()
|
||||
},
|
||||
addToList(account) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ListMembership/setAccount', account)
|
||||
this.$store.dispatch('TimelineSpace/Modals/ListMembership/changeModal', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/setAccount',
|
||||
account
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/changeModal',
|
||||
true
|
||||
)
|
||||
this.$refs.popper.doClose()
|
||||
},
|
||||
confirmMute(account) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeAccount', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/MuteConfirm/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', true)
|
||||
this.$refs.popper.doClose()
|
||||
},
|
||||
unmute(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unmute', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unmute',
|
||||
account
|
||||
)
|
||||
this.$refs.popper.doClose()
|
||||
},
|
||||
block(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/block', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/block',
|
||||
account
|
||||
)
|
||||
this.$refs.popper.doClose()
|
||||
},
|
||||
unblock(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unblock', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unblock',
|
||||
account
|
||||
)
|
||||
this.$refs.popper.doClose()
|
||||
},
|
||||
metadataClick(e) {
|
||||
|
@ -259,32 +360,50 @@ export default {
|
|||
return window.shell.openExternal(link)
|
||||
},
|
||||
subscribe(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/subscribe', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/subscribe',
|
||||
account
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.subscribe_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
unsubscribe(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unsubscribe', account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unsubscribe',
|
||||
account
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.unsubscribe_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,14 +1,34 @@
|
|||
<template>
|
||||
<div id="followers">
|
||||
<DynamicScroller :items="followers" :min-item-size="53" class="scroller" page-mode>
|
||||
<DynamicScroller
|
||||
:items="followers"
|
||||
:min-item-size="53"
|
||||
class="scroller"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.item]" :data-index="index" :watchData="true">
|
||||
<user :user="item" :relationship="targetRelation(item.id)" @followAccount="followAccount" @unfollowAccount="unfollowAccount">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.item]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<user
|
||||
:user="item"
|
||||
:relationship="targetRelation(item.id)"
|
||||
@followAccount="followAccount"
|
||||
@unfollowAccount="unfollowAccount"
|
||||
>
|
||||
</user>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
|
||||
<div
|
||||
class="loading-card"
|
||||
v-loading="lazyLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -22,13 +42,13 @@ export default {
|
|||
components: { User },
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Followers', {
|
||||
followers: state => state.followers,
|
||||
relationships: state => state.relationships,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
followers: (state) => state.followers,
|
||||
relationships: (state) => state.relationships,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
})
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
|
@ -36,78 +56,127 @@ export default {
|
|||
watch: {
|
||||
account: function (_newAccount, _oldAccount) {
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
},
|
||||
destroyed() {
|
||||
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
|
||||
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('sidebar_scrollable') !== undefined &&
|
||||
document.getElementById('sidebar_scrollable') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async load() {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
const followers = await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchFollowers', this.account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', followers)
|
||||
const followers = await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchFollowers',
|
||||
this.account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships',
|
||||
followers
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.followers_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
onScroll(event) {
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('account_profile').clientHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('account_profile').clientHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/lazyFetchFollowers', this.account).catch(err => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Followers/lazyFetchFollowers',
|
||||
this.account
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
targetRelation(id) {
|
||||
return this.relationships.find(r => r.id === id)
|
||||
return this.relationships.find((r) => r.id === id)
|
||||
},
|
||||
async followAccount(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', this.followers)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/follow',
|
||||
account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships',
|
||||
this.followers
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
async unfollowAccount(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', this.followers)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unfollow',
|
||||
account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships',
|
||||
this.followers
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.unfollow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
<template>
|
||||
<div id="follows">
|
||||
<DynamicScroller :items="follows" :min-item-size="53" class="scroller" page-mode>
|
||||
<DynamicScroller
|
||||
:items="follows"
|
||||
:min-item-size="53"
|
||||
class="scroller"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.item]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.item]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<user
|
||||
:user="item"
|
||||
v-bind:key="item.id"
|
||||
|
@ -14,7 +25,11 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
|
||||
<div
|
||||
class="loading-card"
|
||||
v-loading="lazyLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -28,93 +43,142 @@ export default {
|
|||
components: { User },
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Follows', {
|
||||
follows: state => state.follows,
|
||||
relationships: state => state.relationships,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
follows: (state) => state.follows,
|
||||
relationships: (state) => state.relationships,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
})
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
},
|
||||
destroyed() {
|
||||
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
|
||||
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('sidebar_scrollable') !== undefined &&
|
||||
document.getElementById('sidebar_scrollable') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
account: function (_newAccount, _oldAccount) {
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async load() {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
const follows = await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchFollows', this.account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', follows)
|
||||
const follows = await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchFollows',
|
||||
this.account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships',
|
||||
follows
|
||||
)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.follows_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
onScroll(event) {
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('account_profile').clientHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('account_profile').clientHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/lazyFetchFollows', this.account).catch(err => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Follows/lazyFetchFollows',
|
||||
this.account
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
targetRelation(id) {
|
||||
return this.relationships.find(r => r.id === id)
|
||||
return this.relationships.find((r) => r.id === id)
|
||||
},
|
||||
async followAccount(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', this.follows)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/follow',
|
||||
account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships',
|
||||
this.follows
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.follow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
},
|
||||
async unfollowAccount(account) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
true
|
||||
)
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
|
||||
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', this.follows)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/unfollow',
|
||||
account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships',
|
||||
this.follows
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.unfollow_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeLoading',
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
<template>
|
||||
<div class="tabs" id="sidebar_tabs">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick" stretch>
|
||||
<el-tab-pane label="Posts" name="posts"><Posts :account="account" :buffer="buffer" :filters="filters" /></el-tab-pane>
|
||||
<el-tab-pane label="Posts and replies" name="posts_and_replies"
|
||||
><PostsAndReplies :account="account" :buffer="buffer" :filters="filters"
|
||||
<el-tab-pane label="Posts" name="posts"
|
||||
><Posts :account="account" :buffer="buffer" :filters="filters"
|
||||
/></el-tab-pane>
|
||||
<el-tab-pane label="Posts and replies" name="posts_and_replies"
|
||||
><PostsAndReplies
|
||||
:account="account"
|
||||
:buffer="buffer"
|
||||
:filters="filters"
|
||||
/></el-tab-pane>
|
||||
<el-tab-pane label="Media" name="media"
|
||||
><Media :account="account" :buffer="buffer" :filters="filters"
|
||||
/></el-tab-pane>
|
||||
<el-tab-pane label="Media" name="media"><Media :account="account" :buffer="buffer" :filters="filters" /></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -22,17 +29,19 @@ export default {
|
|||
components: {
|
||||
Posts,
|
||||
PostsAndReplies,
|
||||
Media
|
||||
Media,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'posts',
|
||||
defaultBuffer: 200,
|
||||
buffer: 200
|
||||
buffer: 200,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile/Timeline', ['filters'])
|
||||
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile/Timeline', [
|
||||
'filters',
|
||||
]),
|
||||
},
|
||||
mounted() {
|
||||
const timeline = document.getElementById('sidebar_tabs')
|
||||
|
@ -43,8 +52,8 @@ export default {
|
|||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
<template>
|
||||
<div id="timeline">
|
||||
<DynamicScroller :items="timeline" :min-item-size="60" class="scroller" :buffer="buffer" page-mode>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="60"
|
||||
class="scroller"
|
||||
:buffer="buffer"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:key="item.id"
|
||||
|
@ -20,7 +32,11 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
|
||||
<div
|
||||
class="loading-card"
|
||||
v-loading="lazyLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -35,25 +51,32 @@ export default {
|
|||
components: { Toot },
|
||||
data() {
|
||||
return {
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
}),
|
||||
...mapState(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media',
|
||||
{
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}
|
||||
),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened'])
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/clearTimeline')
|
||||
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/clearTimeline'
|
||||
)
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-sidebar', () => {
|
||||
this.focusedId = 0
|
||||
this.$nextTick(function () {
|
||||
|
@ -66,63 +89,93 @@ export default {
|
|||
Event.$off('focus-sidebar')
|
||||
},
|
||||
destroyed() {
|
||||
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
|
||||
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('sidebar_scrollable') !== undefined &&
|
||||
document.getElementById('sidebar_scrollable') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
account: function (_newAccount, _oldAccount) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/clearTimeline')
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/clearTimeline'
|
||||
)
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
load() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/fetchTimeline', this.account).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/fetchTimeline',
|
||||
this.account
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/deleteToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/deleteToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
onScroll(event) {
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('account_profile').clientHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('account_profile').clientHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/lazyFetchTimeline', {
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1]
|
||||
})
|
||||
.catch(err => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media/lazyFetchTimeline',
|
||||
{
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1],
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length - 1) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -131,8 +184,8 @@ export default {
|
|||
focusTimeline() {
|
||||
this.focusedId = 0
|
||||
Event.$emit('focus-timeline')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -17,9 +17,21 @@
|
|||
>
|
||||
</toot>
|
||||
</template>
|
||||
<DynamicScroller :items="timeline" :min-item-size="60" class="scroller" :buffer="buffer" page-mode>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="60"
|
||||
class="scroller"
|
||||
:buffer="buffer"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:key="item.id"
|
||||
|
@ -37,7 +49,11 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
|
||||
<div
|
||||
class="loading-card"
|
||||
v-loading="lazyLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -52,26 +68,33 @@ export default {
|
|||
components: { Toot },
|
||||
data() {
|
||||
return {
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts', {
|
||||
timeline: state => state.timeline,
|
||||
pinnedToots: state => state.pinnedToots,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
}),
|
||||
...mapState(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts',
|
||||
{
|
||||
timeline: (state) => state.timeline,
|
||||
pinnedToots: (state) => state.pinnedToots,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}
|
||||
),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened'])
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/clearTimeline')
|
||||
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/clearTimeline'
|
||||
)
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-sidebar', () => {
|
||||
this.focusedId = 0
|
||||
this.$nextTick(function () {
|
||||
|
@ -84,66 +107,99 @@ export default {
|
|||
Event.$off('focus-sidebar')
|
||||
},
|
||||
destroyed() {
|
||||
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
|
||||
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('sidebar_scrollable') !== undefined &&
|
||||
document.getElementById('sidebar_scrollable') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
account: function (_newAccount, _oldAccount) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/clearTimeline')
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/clearTimeline'
|
||||
)
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
load() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/fetchTimeline', this.account).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/fetchTimeline',
|
||||
this.account
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
onScroll(event) {
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('account_profile').clientHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('account_profile').clientHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/lazyFetchTimeline', {
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1]
|
||||
})
|
||||
.catch(err => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/lazyFetchTimeline',
|
||||
{
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1],
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
updatePinnedToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/updatePinnedToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/updatePinnedToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/deleteToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/deleteToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length - 1) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -152,8 +208,8 @@ export default {
|
|||
focusTimeline() {
|
||||
this.focusedId = 0
|
||||
Event.$emit('focus-timeline')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
<template>
|
||||
<div id="timeline">
|
||||
<DynamicScroller :items="timeline" :min-item-size="60" class="scroller" :buffer="buffer" page-mode>
|
||||
<DynamicScroller
|
||||
:items="timeline"
|
||||
:min-item-size="60"
|
||||
class="scroller"
|
||||
:buffer="buffer"
|
||||
page-mode
|
||||
>
|
||||
<template v-slot="{ item, index, active }">
|
||||
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.uri]"
|
||||
:data-index="index"
|
||||
:watchData="true"
|
||||
>
|
||||
<toot
|
||||
:message="item"
|
||||
:key="item.id"
|
||||
|
@ -20,7 +32,11 @@
|
|||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
|
||||
<div
|
||||
class="loading-card"
|
||||
v-loading="lazyLoading"
|
||||
:element-loading-background="backgroundColor"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -35,25 +51,32 @@ export default {
|
|||
components: { Toot },
|
||||
data() {
|
||||
return {
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies', {
|
||||
timeline: state => state.timeline,
|
||||
lazyLoading: state => state.lazyLoading
|
||||
}),
|
||||
...mapState(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies',
|
||||
{
|
||||
timeline: (state) => state.timeline,
|
||||
lazyLoading: (state) => state.lazyLoading,
|
||||
}
|
||||
),
|
||||
...mapState('App', {
|
||||
backgroundColor: state => state.theme.background_color
|
||||
backgroundColor: (state) => state.theme.background_color,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened'])
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/clearTimeline')
|
||||
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/clearTimeline'
|
||||
)
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.addEventListener('scroll', this.onScroll)
|
||||
Event.$on('focus-sidebar', () => {
|
||||
this.focusedId = 0
|
||||
this.$nextTick(function () {
|
||||
|
@ -66,65 +89,93 @@ export default {
|
|||
Event.$off('focus-sidebar')
|
||||
},
|
||||
destroyed() {
|
||||
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
|
||||
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
|
||||
if (
|
||||
document.getElementById('sidebar_scrollable') !== undefined &&
|
||||
document.getElementById('sidebar_scrollable') !== null
|
||||
) {
|
||||
document
|
||||
.getElementById('sidebar_scrollable')
|
||||
.removeEventListener('scroll', this.onScroll)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
account: function (_newAccount, _oldAccount) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/clearTimeline')
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/clearTimeline'
|
||||
)
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
load() {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/fetchTimeline', this.account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/fetchTimeline',
|
||||
this.account
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/deleteToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/deleteToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
onScroll(event) {
|
||||
// for lazyLoading
|
||||
if (
|
||||
event.target.clientHeight + event.target.scrollTop >= document.getElementById('account_profile').clientHeight - 10 &&
|
||||
event.target.clientHeight + event.target.scrollTop >=
|
||||
document.getElementById('account_profile').clientHeight - 10 &&
|
||||
!this.lazyloading
|
||||
) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/lazyFetchTimeline', {
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1]
|
||||
})
|
||||
.catch(err => {
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/lazyFetchTimeline',
|
||||
{
|
||||
account: this.account,
|
||||
status: this.timeline[this.timeline.length - 1],
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length - 1) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -133,8 +184,8 @@ export default {
|
|||
focusTimeline() {
|
||||
this.focusedId = 0
|
||||
Event.$emit('focus-timeline')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<template>
|
||||
<div class="toot-detail" ref="detail">
|
||||
<div class="toot-ancestors" v-for="(message, index) in ancestors" v-bind:key="'ancestors-' + index">
|
||||
<div
|
||||
class="toot-ancestors"
|
||||
v-for="(message, index) in ancestors"
|
||||
v-bind:key="'ancestors-' + index"
|
||||
>
|
||||
<toot
|
||||
:message="message"
|
||||
:focused="message.uri + message.id === focusedId"
|
||||
|
@ -31,7 +35,11 @@
|
|||
>
|
||||
</toot>
|
||||
</div>
|
||||
<div class="toot-descendants" v-for="(message, index) in descendants" v-bind:key="'descendants' + index">
|
||||
<div
|
||||
class="toot-descendants"
|
||||
v-for="(message, index) in descendants"
|
||||
v-bind:key="'descendants' + index"
|
||||
>
|
||||
<toot
|
||||
:message="message"
|
||||
:focused="message.uri + message.id === focusedId"
|
||||
|
@ -59,18 +67,19 @@ export default {
|
|||
components: { Toot },
|
||||
data() {
|
||||
return {
|
||||
focusedId: null
|
||||
focusedId: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Contents/SideBar/TootDetail', {
|
||||
message: state => state.message,
|
||||
ancestors: state => state.ancestors,
|
||||
descendants: state => state.descendants,
|
||||
timeline: state => state.ancestors.concat([state.message]).concat(state.descendants)
|
||||
message: (state) => state.message,
|
||||
ancestors: (state) => state.ancestors,
|
||||
descendants: (state) => state.descendants,
|
||||
timeline: (state) =>
|
||||
state.ancestors.concat([state.message]).concat(state.descendants),
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Contents/SideBar/TootDetail', ['filters']),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened'])
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
},
|
||||
created() {
|
||||
this.load()
|
||||
|
@ -86,7 +95,7 @@ export default {
|
|||
watch: {
|
||||
message: function () {
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
Event.$emit('focus-timeline')
|
||||
|
@ -102,7 +111,10 @@ export default {
|
|||
},
|
||||
load() {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/TootDetail/fetchToot', this.originalMessage(this.message))
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/fetchToot',
|
||||
this.originalMessage(this.message)
|
||||
)
|
||||
.then(() => {
|
||||
const toot = this.$refs.original
|
||||
toot.scrollIntoView()
|
||||
|
@ -110,40 +122,66 @@ export default {
|
|||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.toot_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
updateAncestorsToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/updateAncestorsToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/updateAncestorsToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteAncestorsToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/deleteAncestorsToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/deleteAncestorsToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
updateToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/updateToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/updateToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/deleteToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/deleteToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
updateDescendantsToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/updateDescendantsToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/updateDescendantsToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
deleteDescendantsToot(message) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/TootDetail/deleteDescendantsToot', message)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/deleteDescendantsToot',
|
||||
message
|
||||
)
|
||||
},
|
||||
focusNext() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex === -1) {
|
||||
this.focusedId = this.timeline[0].uri + this.timeline[0].id
|
||||
} else if (currentIndex < this.timeline.length - 1) {
|
||||
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex + 1].uri +
|
||||
this.timeline[currentIndex + 1].id
|
||||
}
|
||||
},
|
||||
focusPrev() {
|
||||
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
|
||||
const currentIndex = this.timeline.findIndex(
|
||||
(toot) => this.focusedId === toot.uri + toot.id
|
||||
)
|
||||
if (currentIndex > 0) {
|
||||
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
|
||||
this.focusedId =
|
||||
this.timeline[currentIndex - 1].uri +
|
||||
this.timeline[currentIndex - 1].id
|
||||
}
|
||||
},
|
||||
focusToot(message) {
|
||||
|
@ -152,8 +190,8 @@ export default {
|
|||
focusTimeline() {
|
||||
this.focusedId = 0
|
||||
Event.$emit('focus-timeline')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,30 +4,81 @@
|
|||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
<div class="tools">
|
||||
<img src="../../assets/images/loading-spinner-wide.svg" v-show="loading" class="header-loading" />
|
||||
<el-button type="text" class="action" @click="openNewTootModal" :title="$t('header_menu.new_toot')">
|
||||
<img
|
||||
src="../../assets/images/loading-spinner-wide.svg"
|
||||
v-show="loading"
|
||||
class="header-loading"
|
||||
/>
|
||||
<el-button
|
||||
type="text"
|
||||
class="action"
|
||||
@click="openNewTootModal"
|
||||
:title="$t('header_menu.new_toot')"
|
||||
>
|
||||
<font-awesome-icon :icon="['far', 'pen-to-square']" />
|
||||
</el-button>
|
||||
<el-button v-show="reloadable()" type="text" class="action" @click="reload" :title="$t('header_menu.reload')">
|
||||
<el-button
|
||||
v-show="reloadable()"
|
||||
type="text"
|
||||
class="action"
|
||||
@click="reload"
|
||||
:title="$t('header_menu.reload')"
|
||||
>
|
||||
<font-awesome-icon icon="rotate" />
|
||||
</el-button>
|
||||
<el-popover placement="left-start" width="180" popper-class="theme-popover" trigger="click" v-model="TLOptionVisible">
|
||||
<el-popover
|
||||
placement="left-start"
|
||||
width="180"
|
||||
popper-class="theme-popover"
|
||||
trigger="click"
|
||||
v-model="TLOptionVisible"
|
||||
>
|
||||
<div>
|
||||
<el-form role="form" label-position="left" label-width="125px" size="medium">
|
||||
<el-form-item for="show-reblogs" :label="$t('header_menu.option.show_reblogs')">
|
||||
<el-checkbox id="show-reblogs" v-model="showReblogs"></el-checkbox>
|
||||
<el-form
|
||||
role="form"
|
||||
label-position="left"
|
||||
label-width="125px"
|
||||
size="medium"
|
||||
>
|
||||
<el-form-item
|
||||
for="show-reblogs"
|
||||
:label="$t('header_menu.option.show_reblogs')"
|
||||
>
|
||||
<el-checkbox
|
||||
id="show-reblogs"
|
||||
v-model="showReblogs"
|
||||
></el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item for="show-replies" :label="$t('header_menu.option.show_replies')">
|
||||
<el-checkbox id="show-replies" v-model="showReplies"></el-checkbox>
|
||||
<el-form-item
|
||||
for="show-replies"
|
||||
:label="$t('header_menu.option.show_replies')"
|
||||
>
|
||||
<el-checkbox
|
||||
id="show-replies"
|
||||
v-model="showReplies"
|
||||
></el-checkbox>
|
||||
</el-form-item>
|
||||
<el-button type="primary" @click="applyTLOption">{{ $t('header_menu.option.apply') }}</el-button>
|
||||
<el-button type="primary" @click="applyTLOption">{{
|
||||
$t('header_menu.option.apply')
|
||||
}}</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button v-show="TLOption()" slot="reference" type="text" class="action" :title="$t('header_menu.option.title')">
|
||||
<el-button
|
||||
v-show="TLOption()"
|
||||
slot="reference"
|
||||
type="text"
|
||||
class="action"
|
||||
:title="$t('header_menu.option.title')"
|
||||
>
|
||||
<font-awesome-icon icon="sliders" />
|
||||
</el-button>
|
||||
</el-popover>
|
||||
<el-button type="text" class="action" @click="settings" :title="$t('header_menu.settings')">
|
||||
<el-button
|
||||
type="text"
|
||||
class="action"
|
||||
@click="settings"
|
||||
:title="$t('header_menu.settings')"
|
||||
>
|
||||
<font-awesome-icon icon="gear" />
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -43,14 +94,14 @@ export default {
|
|||
return {
|
||||
TLOptionVisible: false,
|
||||
showReblogs: true,
|
||||
showReplies: true
|
||||
showReplies: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/HeaderMenu', {
|
||||
title: state => state.title,
|
||||
loading: state => state.loading
|
||||
})
|
||||
title: (state) => state.title,
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.channelName()
|
||||
|
@ -61,7 +112,7 @@ export default {
|
|||
$route: function () {
|
||||
this.channelName()
|
||||
this.loadTLOption()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
id() {
|
||||
|
@ -70,53 +121,101 @@ export default {
|
|||
channelName() {
|
||||
switch (this.$route.name) {
|
||||
case 'home':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.home'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.home')
|
||||
)
|
||||
break
|
||||
case 'notifications':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.notification'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.notification')
|
||||
)
|
||||
break
|
||||
case 'favourites':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.favourite'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.favourite')
|
||||
)
|
||||
break
|
||||
case 'bookmarks':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.bookmark'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.bookmark')
|
||||
)
|
||||
break
|
||||
case 'mentions':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.mention'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.mention')
|
||||
)
|
||||
break
|
||||
case 'follow-requests':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.follow_requests'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.follow_requests')
|
||||
)
|
||||
break
|
||||
case 'local':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.local'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.local')
|
||||
)
|
||||
break
|
||||
case 'public':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.public'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.public')
|
||||
)
|
||||
break
|
||||
case 'hashtag-list':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.hashtag'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.hashtag')
|
||||
)
|
||||
break
|
||||
case 'tag':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', `#${this.$route.params.tag}`)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
`#${this.$route.params.tag}`
|
||||
)
|
||||
break
|
||||
case 'search':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.search'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.search')
|
||||
)
|
||||
break
|
||||
case 'lists':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.lists'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.lists')
|
||||
)
|
||||
break
|
||||
case 'direct-messages':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.direct_messages'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.direct_messages')
|
||||
)
|
||||
break
|
||||
case 'edit-list':
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.members'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.members')
|
||||
)
|
||||
break
|
||||
case 'list':
|
||||
this.$store.dispatch('TimelineSpace/HeaderMenu/fetchList', this.$route.params.list_id)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/HeaderMenu/fetchList',
|
||||
this.$route.params.list_id
|
||||
)
|
||||
break
|
||||
default:
|
||||
console.log(this.$route)
|
||||
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.home'))
|
||||
this.$store.commit(
|
||||
'TimelineSpace/HeaderMenu/updateTitle',
|
||||
this.$t('header_menu.home')
|
||||
)
|
||||
break
|
||||
}
|
||||
},
|
||||
|
@ -161,8 +260,10 @@ export default {
|
|||
loadTLOption() {
|
||||
switch (this.$route.name) {
|
||||
case 'home':
|
||||
this.showReblogs = this.$store.state.TimelineSpace.Contents.Home.showReblogs
|
||||
this.showReplies = this.$store.state.TimelineSpace.Contents.Home.showReplies
|
||||
this.showReblogs =
|
||||
this.$store.state.TimelineSpace.Contents.Home.showReblogs
|
||||
this.showReplies =
|
||||
this.$store.state.TimelineSpace.Contents.Home.showReplies
|
||||
break
|
||||
default:
|
||||
console.log('Not implemented')
|
||||
|
@ -171,8 +272,14 @@ export default {
|
|||
applyTLOption() {
|
||||
switch (this.$route.name) {
|
||||
case 'home':
|
||||
this.$store.commit('TimelineSpace/Contents/Home/showReblogs', this.showReblogs)
|
||||
this.$store.commit('TimelineSpace/Contents/Home/showReplies', this.showReplies)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Home/showReblogs',
|
||||
this.showReblogs
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/Home/showReplies',
|
||||
this.showReplies
|
||||
)
|
||||
break
|
||||
default:
|
||||
console.log('Not implemented')
|
||||
|
@ -190,8 +297,8 @@ export default {
|
|||
settings() {
|
||||
const url = `/${this.id()}/settings`
|
||||
this.$router.push(url)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export default {
|
|||
AddListMember,
|
||||
MuteConfirm,
|
||||
Shortcut,
|
||||
Report
|
||||
}
|
||||
Report,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
<template>
|
||||
<el-dialog :title="$t('modals.add_list_member.title')" :visible.sync="addListMemberModal" width="400px" class="add-member">
|
||||
<el-dialog
|
||||
:title="$t('modals.add_list_member.title')"
|
||||
:visible.sync="addListMemberModal"
|
||||
width="400px"
|
||||
class="add-member"
|
||||
>
|
||||
<div class="search-account" :element-loading-background="loadingBackground">
|
||||
<el-form :inline="true">
|
||||
<input v-model="name" placeholder="Account name" class="account-name" v-shortkey="['enter']" @shortkey="search" autofocus />
|
||||
<input
|
||||
v-model="name"
|
||||
placeholder="Account name"
|
||||
class="account-name"
|
||||
v-shortkey="['enter']"
|
||||
@shortkey="search"
|
||||
autofocus
|
||||
/>
|
||||
<el-button type="text" class="search" @click="search">
|
||||
<font-awesome-icon icon="magnifying-glass" />
|
||||
</el-button>
|
||||
|
@ -38,23 +50,26 @@ export default {
|
|||
name: 'add-list-member',
|
||||
data() {
|
||||
return {
|
||||
name: ''
|
||||
name: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
loadingBackground: state => state.App.theme.wrapper_mask_color,
|
||||
accounts: state => state.TimelineSpace.Modals.AddListMember.accounts,
|
||||
listId: state => state.TimelineSpace.Modals.AddListMember.targetListId
|
||||
loadingBackground: (state) => state.App.theme.wrapper_mask_color,
|
||||
accounts: (state) => state.TimelineSpace.Modals.AddListMember.accounts,
|
||||
listId: (state) => state.TimelineSpace.Modals.AddListMember.targetListId,
|
||||
}),
|
||||
addListMemberModal: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.AddListMember.modalOpen
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/AddListMember/changeModal', value)
|
||||
}
|
||||
}
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/AddListMember/changeModal',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -65,23 +80,29 @@ export default {
|
|||
}
|
||||
},
|
||||
search() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/AddListMember/search', this.name)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/AddListMember/search',
|
||||
this.name
|
||||
)
|
||||
},
|
||||
add(user) {
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Modals/AddListMember/add', user)
|
||||
.then(() => {
|
||||
this.addListMemberModal = false
|
||||
this.$store.dispatch('TimelineSpace/Contents/Lists/Edit/fetchMembers', this.listId)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/Lists/Edit/fetchMembers',
|
||||
this.listId
|
||||
)
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.add_user_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,64 +1,108 @@
|
|||
<template>
|
||||
<transition name="image-viewer">
|
||||
<div id="image" v-show="modalOpen" @click="close" :aria-hidden="!modalOpen" aria-modal="true" role="dialog">
|
||||
<div class="image-wrapper" v-shortkey="modalOpen ? {close: ['esc']} : {}" @shortkey="closeHandle">
|
||||
<div class="image-header">
|
||||
<el-button type="text" icon="el-icon-close" @click="close" class="close-button"></el-button>
|
||||
</div>
|
||||
<div class="image-content" role="presentation">
|
||||
<span class="button-area"><el-button type="text" v-show="showLeft" v-shortkey="['arrowleft']" @shortkey.native="decrementIndex()"><i class="el-icon-arrow-left" @click.stop="decrementIndex"></i></el-button></span>
|
||||
<Media :src="imageURL" :type="imageType"></Media>
|
||||
<span class="button-area"><el-button type="text" v-show="showRight" v-shortkey="['arrowright']" @shortkey.native="incrementIndex()"><i class="el-icon-arrow-right" @click.stop="incrementIndex"></i></el-button></span>
|
||||
<transition name="image-viewer">
|
||||
<div
|
||||
id="image"
|
||||
v-show="modalOpen"
|
||||
@click="close"
|
||||
:aria-hidden="!modalOpen"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
>
|
||||
<div
|
||||
class="image-wrapper"
|
||||
v-shortkey="modalOpen ? { close: ['esc'] } : {}"
|
||||
@shortkey="closeHandle"
|
||||
>
|
||||
<div class="image-header">
|
||||
<el-button
|
||||
type="text"
|
||||
:icon="ElIconClose"
|
||||
@click="close"
|
||||
class="close-button"
|
||||
></el-button>
|
||||
</div>
|
||||
<div class="image-content" role="presentation">
|
||||
<span class="button-area"
|
||||
><el-button
|
||||
type="text"
|
||||
v-show="showLeft"
|
||||
v-shortkey="['arrowleft']"
|
||||
@shortkey.native="decrementIndex()"
|
||||
><el-icon><el-icon-arrow-left /></el-icon></el-button
|
||||
></span>
|
||||
<Media :src="imageURL" :type="imageType"></Media>
|
||||
<span class="button-area"
|
||||
><el-button
|
||||
type="text"
|
||||
v-show="showRight"
|
||||
v-shortkey="['arrowright']"
|
||||
@shortkey.native="incrementIndex()"
|
||||
><el-icon><el-icon-arrow-right /></el-icon></el-button
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
ArrowLeft as ElIconArrowLeft,
|
||||
ArrowRight as ElIconArrowRight,
|
||||
Close as ElIconClose,
|
||||
} from '@element-plus/icons'
|
||||
import Media from './Media'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'image-viewer',
|
||||
components: {
|
||||
Media
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
modalOpen: state => state.TimelineSpace.Modals.ImageViewer.modalOpen
|
||||
}),
|
||||
imageURL () {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageURL']
|
||||
},
|
||||
imageType () {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageType']
|
||||
},
|
||||
showLeft () {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showLeft']
|
||||
},
|
||||
showRight () {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showRight']
|
||||
data() {
|
||||
return {
|
||||
ElIconClose,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Media,
|
||||
ElIconArrowLeft,
|
||||
ElIconArrowRight,
|
||||
},
|
||||
name: 'image-viewer',
|
||||
computed: {
|
||||
...mapState({
|
||||
modalOpen: (state) => state.TimelineSpace.Modals.ImageViewer.modalOpen,
|
||||
}),
|
||||
imageURL() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageURL']
|
||||
},
|
||||
imageType() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageType']
|
||||
},
|
||||
showLeft() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showLeft']
|
||||
},
|
||||
showRight() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showRight']
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
close() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/closeModal')
|
||||
},
|
||||
decrementIndex () {
|
||||
if (this.showLeft) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/decrementIndex')
|
||||
decrementIndex() {
|
||||
if (this.showLeft)
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/decrementIndex')
|
||||
},
|
||||
incrementIndex () {
|
||||
if (this.showRight) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/incrementIndex')
|
||||
incrementIndex() {
|
||||
if (this.showRight)
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/incrementIndex')
|
||||
},
|
||||
closeHandle (event) {
|
||||
closeHandle(event) {
|
||||
switch (event.srcKey) {
|
||||
case 'close':
|
||||
this.close()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -75,7 +119,7 @@ export default {
|
|||
.image-header {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding: 8px 8px 0 0 ;
|
||||
padding: 8px 8px 0 0;
|
||||
color: #409eff;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
|
@ -93,10 +137,12 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.image-viewer-enter-active, .image-viewer-leave-active {
|
||||
.image-viewer-enter-active,
|
||||
.image-viewer-leave-active {
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
.image-viewer-enter, .image-viewer-leave-to {
|
||||
.image-viewer-enter,
|
||||
.image-viewer-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
.button-area {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="jumpModal"
|
||||
width="440px"
|
||||
class="jump-modal">
|
||||
<el-dialog :visible.sync="jumpModal" width="440px" class="jump-modal">
|
||||
<el-form class="jump-form" v-on:submit.prevent="jump">
|
||||
<div class="channel">
|
||||
<input
|
||||
|
@ -10,11 +7,26 @@
|
|||
v-model="channel"
|
||||
:placeholder="$t('modals.jump.jump_to')"
|
||||
ref="channel"
|
||||
v-shortkey="shortcutEnabled ? {next: ['arrowdown'], prev: ['arrowup'], select: ['enter']} : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? { next: ['arrowdown'], prev: ['arrowup'], select: ['enter'] }
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleKey"
|
||||
/>
|
||||
/>
|
||||
<ul class="channel-list">
|
||||
<li v-for="c in filterdChannel" :class="c.name === selectedChannel.name ? 'channel-list-item selected' : 'channel-list-item'" @click="jump(c)" @mouseover="changeSelected(c)">{{ c.name }}</li>
|
||||
<li
|
||||
v-for="c in filterdChannel"
|
||||
:class="
|
||||
c.name === selectedChannel.name
|
||||
? 'channel-list-item selected'
|
||||
: 'channel-list-item'
|
||||
"
|
||||
@click="jump(c)"
|
||||
@mouseover="changeSelected(c)"
|
||||
>
|
||||
{{ c.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Dummy form to guard submitting with enter -->
|
||||
|
@ -32,35 +44,41 @@ export default {
|
|||
name: 'jump',
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/Jump', {
|
||||
channelList: state => state.defaultChannelList.concat(state.tagChannelList).concat(state.listChannelList),
|
||||
selectedChannel: state => state.selectedChannel
|
||||
channelList: (state) =>
|
||||
state.defaultChannelList
|
||||
.concat(state.tagChannelList)
|
||||
.concat(state.listChannelList),
|
||||
selectedChannel: (state) => state.selectedChannel,
|
||||
}),
|
||||
channel: {
|
||||
get () {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.Jump.channel
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/updateChannel', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
filterdChannel () {
|
||||
filterdChannel() {
|
||||
return this.filterChannelForm()
|
||||
},
|
||||
jumpModal: {
|
||||
get () {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.Jump.modalOpen
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/changeModal', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
shortcutEnabled: function () {
|
||||
return this.jumpModal
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
channel: function (_newChannel, _oldChannel) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', this.filterChannelForm()[0])
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/Jump/changeSelected',
|
||||
this.filterChannelForm()[0]
|
||||
)
|
||||
},
|
||||
jumpModal: function (newModal, oldModal) {
|
||||
if (!oldModal && newModal) {
|
||||
|
@ -72,44 +90,50 @@ export default {
|
|||
} else {
|
||||
this.channel = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
filterChannelForm () {
|
||||
filterChannelForm() {
|
||||
return this.channelList.filter((c) => {
|
||||
return c.name.toLowerCase().indexOf(this.channel.toLowerCase()) !== -1
|
||||
})
|
||||
},
|
||||
nextChannel () {
|
||||
nextChannel() {
|
||||
const filterd = this.filterChannelForm()
|
||||
const i = filterd.findIndex((e) => {
|
||||
return e.name === this.selectedChannel.name
|
||||
})
|
||||
if (i !== undefined && i < (filterd.length - 1)) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', filterd[i + 1])
|
||||
if (i !== undefined && i < filterd.length - 1) {
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/Jump/changeSelected',
|
||||
filterd[i + 1]
|
||||
)
|
||||
}
|
||||
},
|
||||
prevChannel () {
|
||||
prevChannel() {
|
||||
const filterd = this.filterChannelForm()
|
||||
const i = filterd.findIndex((e) => {
|
||||
return e.name === this.selectedChannel.name
|
||||
})
|
||||
if (i !== undefined && i > 0) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', filterd[i - 1])
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/Jump/changeSelected',
|
||||
filterd[i - 1]
|
||||
)
|
||||
}
|
||||
},
|
||||
changeSelected (channel) {
|
||||
changeSelected(channel) {
|
||||
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', channel)
|
||||
},
|
||||
jumpCurrentSelected () {
|
||||
jumpCurrentSelected() {
|
||||
if (this.jumpModal) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/Jump/jumpCurrentSelected')
|
||||
}
|
||||
},
|
||||
jump (channel) {
|
||||
jump(channel) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/Jump/jump', channel)
|
||||
},
|
||||
handleKey (event) {
|
||||
handleKey(event) {
|
||||
switch (event.srcKey) {
|
||||
case 'next':
|
||||
this.nextChannel()
|
||||
|
@ -123,8 +147,8 @@ export default {
|
|||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<template>
|
||||
<el-dialog :title="$t('modals.list_membership.title')" :visible.sync="listMembershipModal" width="400px" class="list-membership-modal">
|
||||
<el-dialog
|
||||
:title="$t('modals.list_membership.title')"
|
||||
:visible.sync="listMembershipModal"
|
||||
width="400px"
|
||||
class="list-membership-modal"
|
||||
>
|
||||
<el-checkbox-group v-model="belongToLists" v-loading="loading">
|
||||
<table class="lists">
|
||||
<tbody>
|
||||
|
@ -21,63 +26,76 @@ export default {
|
|||
name: 'list-membership',
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
account: state => state.TimelineSpace.Modals.ListMembership.account,
|
||||
lists: state => state.TimelineSpace.Modals.ListMembership.lists
|
||||
account: (state) => state.TimelineSpace.Modals.ListMembership.account,
|
||||
lists: (state) => state.TimelineSpace.Modals.ListMembership.lists,
|
||||
}),
|
||||
listMembershipModal: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.ListMembership.modalOpen
|
||||
},
|
||||
set(value) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ListMembership/changeModal', value)
|
||||
}
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/changeModal',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
belongToLists: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.ListMembership.belongToLists.map(l => l.id)
|
||||
return this.$store.state.TimelineSpace.Modals.ListMembership.belongToLists.map(
|
||||
(l) => l.id
|
||||
)
|
||||
},
|
||||
set(value) {
|
||||
this.loading = true
|
||||
return this.$store
|
||||
.dispatch('TimelineSpace/Modals/ListMembership/changeBelongToLists', value)
|
||||
.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/changeBelongToLists',
|
||||
value
|
||||
)
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.update_list_memberships_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
.finally(() => (this.loading = false))
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
listMembershipModal: function (newState, oldState) {
|
||||
if (!oldState && newState) {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async init() {
|
||||
this.loading = true
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Modals/ListMembership/fetchListMembership', this.account)
|
||||
await this.$store.dispatch('TimelineSpace/Modals/ListMembership/fetchLists')
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/fetchListMembership',
|
||||
this.account
|
||||
)
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/ListMembership/fetchLists'
|
||||
)
|
||||
} catch (err) {
|
||||
this.$message({
|
||||
message: this.$t('message.lists_fetch_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,32 @@
|
|||
<template>
|
||||
<div id="current-media" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.8)">
|
||||
<video :src="src" v-if="isMovieFile()" autoplay loop controls v-on:loadstart="loaded()"></video>
|
||||
<video :src="src" v-else-if="isGIF()" autoplay loop v-on:loadstart="loaded()"></video>
|
||||
<video :src="src" v-else-if="isAudio()" autoplay loop controls v-on:loadstart="loaded()"></video>
|
||||
<div
|
||||
id="current-media"
|
||||
v-loading="loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
>
|
||||
<video
|
||||
:src="src"
|
||||
v-if="isMovieFile()"
|
||||
autoplay
|
||||
loop
|
||||
controls
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<video
|
||||
:src="src"
|
||||
v-else-if="isGIF()"
|
||||
autoplay
|
||||
loop
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<video
|
||||
:src="src"
|
||||
v-else-if="isAudio()"
|
||||
autoplay
|
||||
loop
|
||||
controls
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<img :src="imageSrc" v-else v-on:load="loaded()" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -15,16 +39,16 @@ export default {
|
|||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imageSrc: this.src
|
||||
imageSrc: this.src,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -38,12 +62,12 @@ export default {
|
|||
console.error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
loading: state => state.TimelineSpace.Modals.ImageViewer.loading
|
||||
})
|
||||
loading: (state) => state.TimelineSpace.Modals.ImageViewer.loading,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
isMovieFile() {
|
||||
|
@ -57,8 +81,8 @@ export default {
|
|||
},
|
||||
async loaded() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/loaded')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="$t('modals.mute_confirm.title')"
|
||||
:visible.sync="muteConfirmModal"
|
||||
width="400px"
|
||||
custom-class="mute-confirm"
|
||||
<el-dialog
|
||||
:title="$t('modals.mute_confirm.title')"
|
||||
:visible.sync="muteConfirmModal"
|
||||
width="400px"
|
||||
custom-class="mute-confirm"
|
||||
>
|
||||
<el-form class="description">
|
||||
<el-form-item for="notify" :label="$t('modals.mute_confirm.body')">
|
||||
<el-switch id="notify" v-model="notify"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeModal">{{ $t('modals.mute_confirm.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ $t('modals.mute_confirm.ok') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-form class="description">
|
||||
<el-form-item for="notify" :label="$t('modals.mute_confirm.body')">
|
||||
<el-switch id="notify" v-model="notify"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeModal">{{
|
||||
$t('modals.mute_confirm.cancel')
|
||||
}}</el-button>
|
||||
<el-button type="primary" @click="submit">{{
|
||||
$t('modals.mute_confirm.ok')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -22,33 +26,39 @@ import { mapState } from 'vuex'
|
|||
|
||||
export default {
|
||||
name: 'MuteConfirm',
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
notify: true
|
||||
notify: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/MuteConfirm', {
|
||||
account: state => state.account
|
||||
account: (state) => state.account,
|
||||
}),
|
||||
muteConfirmModal: {
|
||||
get () {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.MuteConfirm.modalOpen
|
||||
},
|
||||
set (value) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', value)
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/MuteConfirm/changeModal',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeModal () {
|
||||
closeModal() {
|
||||
this.muteConfirmModal = false
|
||||
},
|
||||
async submit () {
|
||||
async submit() {
|
||||
this.closeModal()
|
||||
await this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/submit', this.notify)
|
||||
}
|
||||
}
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/MuteConfirm/submit',
|
||||
this.notify
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,10 +9,21 @@
|
|||
ref="dialog"
|
||||
>
|
||||
<el-form v-on:submit.prevent="toot" role="form">
|
||||
<Quote :message="quoteToMessage" :displayNameStyle="displayNameStyle" v-if="quoteToMessage !== null" ref="quote"></Quote>
|
||||
<Quote
|
||||
:message="quoteToMessage"
|
||||
:displayNameStyle="displayNameStyle"
|
||||
v-if="quoteToMessage !== null"
|
||||
ref="quote"
|
||||
></Quote>
|
||||
<div class="spoiler" v-if="showContentWarning" ref="spoiler">
|
||||
<div class="el-input">
|
||||
<input type="text" class="el-input__inner" :placeholder="$t('modals.new_toot.cw')" v-model="spoiler" v-shortkey.avoid />
|
||||
<input
|
||||
type="text"
|
||||
class="el-input__inner"
|
||||
:placeholder="$t('modals.new_toot.cw')"
|
||||
v-model="spoiler"
|
||||
v-shortkey.avoid
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Status
|
||||
|
@ -36,9 +47,18 @@
|
|||
ref="poll"
|
||||
></Poll>
|
||||
<div class="preview" ref="preview">
|
||||
<div class="image-wrapper" v-for="media in attachedMedias" v-bind:key="media.id">
|
||||
<div
|
||||
class="image-wrapper"
|
||||
v-for="media in attachedMedias"
|
||||
v-bind:key="media.id"
|
||||
>
|
||||
<img :src="media.preview_url" class="preview-image" />
|
||||
<el-button type="text" @click="removeAttachment(media)" class="remove-image"><font-awesome-icon icon="circle-xmark" /></el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="removeAttachment(media)"
|
||||
class="remove-image"
|
||||
><font-awesome-icon icon="circle-xmark"
|
||||
/></el-button>
|
||||
<textarea
|
||||
maxlength="420"
|
||||
class="image-description"
|
||||
|
@ -55,19 +75,40 @@
|
|||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<div class="upload-image">
|
||||
<el-button size="default" type="text" @click="selectImage" :title="$t('modals.new_toot.footer.add_image')">
|
||||
<el-button
|
||||
size="default"
|
||||
type="text"
|
||||
@click="selectImage"
|
||||
:title="$t('modals.new_toot.footer.add_image')"
|
||||
>
|
||||
<font-awesome-icon icon="camera" />
|
||||
</el-button>
|
||||
<input name="image" type="file" class="image-input" ref="image" @change="onChangeImage" :key="attachedMediaId" />
|
||||
<input
|
||||
name="image"
|
||||
type="file"
|
||||
class="image-input"
|
||||
ref="image"
|
||||
@change="onChangeImage"
|
||||
:key="attachedMediaId"
|
||||
/>
|
||||
</div>
|
||||
<div class="poll">
|
||||
<el-button size="default" type="text" @click="togglePollForm" :title="$t('modals.new_toot.footer.poll')">
|
||||
<el-button
|
||||
size="default"
|
||||
type="text"
|
||||
@click="togglePollForm"
|
||||
:title="$t('modals.new_toot.footer.poll')"
|
||||
>
|
||||
<font-awesome-icon icon="square-poll-horizontal" />
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="privacy">
|
||||
<el-dropdown trigger="click" @command="changeVisibility">
|
||||
<el-button size="default" type="text" :title="$t('modals.new_toot.footer.change_visibility')">
|
||||
<el-button
|
||||
size="default"
|
||||
type="text"
|
||||
:title="$t('modals.new_toot.footer.change_visibility')"
|
||||
>
|
||||
<font-awesome-icon :icon="visibilityIcon" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
@ -84,7 +125,11 @@
|
|||
{{ $t(visibilityList.Private.name) }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="visibilityList.Direct.value">
|
||||
<font-awesome-icon icon="envelope" class="privacy-icon" size="sm" />
|
||||
<font-awesome-icon
|
||||
icon="envelope"
|
||||
class="privacy-icon"
|
||||
size="sm"
|
||||
/>
|
||||
{{ $t(visibilityList.Direct.name) }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
|
@ -127,13 +172,27 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<div class="info">
|
||||
<img src="../../../assets/images/loading-spinner-wide.svg" v-show="loading" class="loading" />
|
||||
<img
|
||||
src="../../../assets/images/loading-spinner-wide.svg"
|
||||
v-show="loading"
|
||||
class="loading"
|
||||
/>
|
||||
<span class="text-count">{{ tootMax - status.length }}</span>
|
||||
|
||||
<el-button class="toot-action" size="small" @click="closeConfirm(close)">{{ $t('modals.new_toot.cancel') }}</el-button>
|
||||
<el-button class="toot-action" size="small" type="primary" @click="toot" :loading="blockSubmit">{{
|
||||
$t('modals.new_toot.toot')
|
||||
}}</el-button>
|
||||
<el-button
|
||||
class="toot-action"
|
||||
size="small"
|
||||
@click="closeConfirm(close)"
|
||||
>{{ $t('modals.new_toot.cancel') }}</el-button
|
||||
>
|
||||
<el-button
|
||||
class="toot-action"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="toot"
|
||||
:loading="blockSubmit"
|
||||
>{{ $t('modals.new_toot.toot') }}</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
@ -147,7 +206,13 @@ import Visibility from '~/src/constants/visibility'
|
|||
import Status from './NewToot/Status'
|
||||
import Poll from './NewToot/Poll'
|
||||
import Quote from './NewToot/Quote'
|
||||
import { NewTootTootLength, NewTootAttachLength, NewTootModalOpen, NewTootBlockSubmit, NewTootPollInvalid } from '@/errors/validations'
|
||||
import {
|
||||
NewTootTootLength,
|
||||
NewTootAttachLength,
|
||||
NewTootModalOpen,
|
||||
NewTootBlockSubmit,
|
||||
NewTootPollInvalid,
|
||||
} from '@/errors/validations'
|
||||
import { Event } from '~/src/renderer/components/event'
|
||||
|
||||
export default {
|
||||
|
@ -155,7 +220,7 @@ export default {
|
|||
components: {
|
||||
Status,
|
||||
Poll,
|
||||
Quote
|
||||
Quote,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -167,30 +232,30 @@ export default {
|
|||
polls: [],
|
||||
pollExpire: {
|
||||
label: this.$t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
value: 3600 * 24,
|
||||
},
|
||||
statusHeight: 240
|
||||
statusHeight: 240,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/NewToot', {
|
||||
replyToId: state => {
|
||||
replyToId: (state) => {
|
||||
if (state.replyToMessage !== null) {
|
||||
return state.replyToMessage.id
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
quoteToMessage: state => state.quoteToMessage,
|
||||
attachedMedias: state => state.attachedMedias,
|
||||
attachedMediaId: state => state.attachedMediaId,
|
||||
mediaDescriptions: state => state.mediaDescriptions,
|
||||
blockSubmit: state => state.blockSubmit,
|
||||
visibility: state => state.visibility,
|
||||
sensitive: state => state.sensitive,
|
||||
initialStatus: state => state.initialStatus,
|
||||
initialSpoiler: state => state.initialSpoiler,
|
||||
visibilityIcon: state => {
|
||||
quoteToMessage: (state) => state.quoteToMessage,
|
||||
attachedMedias: (state) => state.attachedMedias,
|
||||
attachedMediaId: (state) => state.attachedMediaId,
|
||||
mediaDescriptions: (state) => state.mediaDescriptions,
|
||||
blockSubmit: (state) => state.blockSubmit,
|
||||
visibility: (state) => state.visibility,
|
||||
sensitive: (state) => state.sensitive,
|
||||
initialStatus: (state) => state.initialStatus,
|
||||
initialSpoiler: (state) => state.initialSpoiler,
|
||||
visibilityIcon: (state) => {
|
||||
switch (state.visibility) {
|
||||
case Visibility.Public.value:
|
||||
return 'globe'
|
||||
|
@ -204,13 +269,13 @@ export default {
|
|||
return 'globe'
|
||||
}
|
||||
},
|
||||
loading: state => state.loading
|
||||
loading: (state) => state.loading,
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
tootMax: state => state.tootMax
|
||||
tootMax: (state) => state.tootMax,
|
||||
}),
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals/NewToot', ['hashtagInserting']),
|
||||
newTootModal: {
|
||||
|
@ -223,16 +288,19 @@ export default {
|
|||
} else {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/closeModal')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
pinedHashtag: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.NewToot.pinedHashtag
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changePinedHashtag', value)
|
||||
}
|
||||
}
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/NewToot/changePinedHashtag',
|
||||
value
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/setupLoading')
|
||||
|
@ -251,12 +319,14 @@ export default {
|
|||
this.status = this.initialStatus
|
||||
this.spoiler = this.initialSpoiler
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.filteredAccount = []
|
||||
const spoilerHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
const spoilerHeight = this.$refs.spoiler
|
||||
? this.$refs.spoiler.offsetHeight
|
||||
: 0
|
||||
this.showContentWarning = false
|
||||
this.spoiler = ''
|
||||
this.statusHeight = this.statusHeight + spoilerHeight
|
||||
|
@ -265,12 +335,16 @@ export default {
|
|||
this.polls = []
|
||||
this.pollExpire = {
|
||||
label: this.$t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
value: 3600 * 24,
|
||||
}
|
||||
this.statusHeight = this.statusHeight + pollHeight
|
||||
const quoteHeight = this.$refs.quote ? this.$refs.quote.$el.offsetHeight : 0
|
||||
const quoteHeight = this.$refs.quote
|
||||
? this.$refs.quote.$el.offsetHeight
|
||||
: 0
|
||||
this.statusHeight = this.statusHeight + quoteHeight
|
||||
const attachmentHeight = this.$refs.preview ? this.$refs.preview.offsetHeight : 0
|
||||
const attachmentHeight = this.$refs.preview
|
||||
? this.$refs.preview.offsetHeight
|
||||
: 0
|
||||
this.statusHeight = this.statusHeight + attachmentHeight
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/resetMediaCount')
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/closeModal')
|
||||
|
@ -280,36 +354,48 @@ export default {
|
|||
status: this.status,
|
||||
spoiler: this.spoiler,
|
||||
polls: this.polls,
|
||||
pollExpireSeconds: this.pollExpire.value
|
||||
pollExpireSeconds: this.pollExpire.value,
|
||||
}
|
||||
|
||||
try {
|
||||
const status = await this.$store.dispatch('TimelineSpace/Modals/NewToot/postToot', form)
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/updateHashtags', status.tags)
|
||||
const status = await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/postToot',
|
||||
form
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/updateHashtags',
|
||||
status.tags
|
||||
)
|
||||
this.close()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
if (err instanceof NewTootTootLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.toot_length', { min: 1, max: this.tootMax }),
|
||||
type: 'error'
|
||||
message: this.$t('validation.new_toot.toot_length', {
|
||||
min: 1,
|
||||
max: this.tootMax,
|
||||
}),
|
||||
type: 'error',
|
||||
})
|
||||
} else if (err instanceof NewTootAttachLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else if (err instanceof NewTootPollInvalid) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.poll_invalid'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else if (err instanceof NewTootModalOpen || err instanceof NewTootBlockSubmit) {
|
||||
} else if (
|
||||
err instanceof NewTootModalOpen ||
|
||||
err instanceof NewTootBlockSubmit
|
||||
) {
|
||||
// Nothing
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.toot_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -318,21 +404,26 @@ export default {
|
|||
this.$refs.image.click()
|
||||
},
|
||||
onChangeImage(e) {
|
||||
if (e.target.files.item(0) === null || e.target.files.item(0) === undefined) {
|
||||
if (
|
||||
e.target.files.item(0) === null ||
|
||||
e.target.files.item(0) === undefined
|
||||
) {
|
||||
return
|
||||
}
|
||||
const file = e.target.files.item(0)
|
||||
if (!file.type.includes('image') && !file.type.includes('video')) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_image'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
return
|
||||
}
|
||||
this.updateImage(file)
|
||||
},
|
||||
onPaste(e) {
|
||||
const mimeTypes = window.clipboard.availableFormats().filter(type => type.startsWith('image'))
|
||||
const mimeTypes = window.clipboard
|
||||
.availableFormats()
|
||||
.filter((type) => type.startsWith('image'))
|
||||
if (mimeTypes.length === 0) {
|
||||
return
|
||||
}
|
||||
|
@ -352,33 +443,42 @@ export default {
|
|||
this.$store
|
||||
.dispatch('TimelineSpace/Modals/NewToot/uploadImage', file)
|
||||
.then(() => {
|
||||
this.statusHeight = this.statusHeight - this.$refs.preview.offsetHeight
|
||||
this.statusHeight =
|
||||
this.statusHeight - this.$refs.preview.offsetHeight
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
if (err instanceof NewTootAttachLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.attach_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
removeAttachment(media) {
|
||||
const previousHeight = this.$refs.preview.offsetHeight
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/removeMedia', media).then(() => {
|
||||
this.statusHeight = this.statusHeight + previousHeight
|
||||
})
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Modals/NewToot/removeMedia', media)
|
||||
.then(() => {
|
||||
this.statusHeight = this.statusHeight + previousHeight
|
||||
})
|
||||
},
|
||||
changeVisibility(level) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changeVisibilityValue', level)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/NewToot/changeVisibilityValue',
|
||||
level
|
||||
)
|
||||
},
|
||||
changeSensitive() {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changeSensitive', !this.sensitive)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/NewToot/changeSensitive',
|
||||
!this.sensitive
|
||||
)
|
||||
},
|
||||
closeConfirm(done) {
|
||||
if (this.status.length === 0) {
|
||||
|
@ -386,19 +486,24 @@ export default {
|
|||
} else {
|
||||
this.$confirm(this.$t('modals.new_toot.close_confirm'), {
|
||||
confirmButtonText: this.$t('modals.new_toot.close_confirm_ok'),
|
||||
cancelButtonText: this.$t('modals.new_toot.close_confirm_cancel')
|
||||
cancelButtonText: this.$t('modals.new_toot.close_confirm_cancel'),
|
||||
})
|
||||
.then(_ => {
|
||||
.then((_) => {
|
||||
done()
|
||||
})
|
||||
.catch(_ => {})
|
||||
.catch((_) => {})
|
||||
}
|
||||
},
|
||||
updateDescription(id, value) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/updateMediaDescription', { id: id, description: value })
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Modals/NewToot/updateMediaDescription',
|
||||
{ id: id, description: value }
|
||||
)
|
||||
},
|
||||
async togglePollForm() {
|
||||
const previousHeight = this.$refs.poll ? this.$refs.poll.$el.offsetHeight : 0
|
||||
const previousHeight = this.$refs.poll
|
||||
? this.$refs.poll.$el.offsetHeight
|
||||
: 0
|
||||
const toggle = () => {
|
||||
this.openPoll = !this.openPoll
|
||||
if (this.openPoll) {
|
||||
|
@ -430,7 +535,9 @@ export default {
|
|||
this.pollExpire = obj
|
||||
},
|
||||
async toggleContentWarning() {
|
||||
const previousHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
const previousHeight = this.$refs.spoiler
|
||||
? this.$refs.spoiler.offsetHeight
|
||||
: 0
|
||||
await (this.showContentWarning = !this.showContentWarning)
|
||||
if (this.showContentWarning) {
|
||||
this.statusHeight = this.statusHeight - this.$refs.spoiler.offsetHeight
|
||||
|
@ -441,7 +548,8 @@ export default {
|
|||
handleResize(event) {
|
||||
// Ignore when the modal height already reach window height.
|
||||
const vHeight = this.$refs.dialog.$el.firstChild.style.marginTop
|
||||
const marginTop = (document.documentElement.clientHeight / 100) * parseInt(vHeight)
|
||||
const marginTop =
|
||||
(document.documentElement.clientHeight / 100) * parseInt(vHeight)
|
||||
const limitHeight = document.documentElement.clientHeight - marginTop - 80
|
||||
if (this.$refs.dialog.$el.firstChild.offsetHeight >= limitHeight) {
|
||||
return
|
||||
|
@ -449,13 +557,25 @@ export default {
|
|||
// When emoji picker is opened, resize event has to be stopped.
|
||||
const style = this.$refs.dialog.$el.firstChild.style
|
||||
if (style.overflow === '' || style.overflow === 'hidden') {
|
||||
const pollHeight = this.$refs.poll ? this.$refs.poll.$el.offsetHeight : 0
|
||||
const spoilerHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
const quoteHeight = this.$refs.quote ? this.$refs.quote.$el.offsetHeight : 0
|
||||
const pollHeight = this.$refs.poll
|
||||
? this.$refs.poll.$el.offsetHeight
|
||||
: 0
|
||||
const spoilerHeight = this.$refs.spoiler
|
||||
? this.$refs.spoiler.offsetHeight
|
||||
: 0
|
||||
const quoteHeight = this.$refs.quote
|
||||
? this.$refs.quote.$el.offsetHeight
|
||||
: 0
|
||||
const headerHeight = 54
|
||||
const footerHeight = 63
|
||||
this.statusHeight =
|
||||
event.height - footerHeight - headerHeight - this.$refs.preview.offsetHeight - pollHeight - spoilerHeight - quoteHeight
|
||||
event.height -
|
||||
footerHeight -
|
||||
headerHeight -
|
||||
this.$refs.preview.offsetHeight -
|
||||
pollHeight -
|
||||
spoilerHeight -
|
||||
quoteHeight
|
||||
}
|
||||
},
|
||||
innerElementOpened(open) {
|
||||
|
@ -464,8 +584,8 @@ export default {
|
|||
} else {
|
||||
this.$refs.dialog.$el.firstChild.style.overflow = 'hidden'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -541,7 +661,12 @@ export default {
|
|||
border: 0;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
background: linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0, rgba(0, 0, 0, 0.35) 80%, transparent);
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(0, 0, 0, 0.8) 0,
|
||||
rgba(0, 0, 0, 0.35) 80%,
|
||||
transparent
|
||||
);
|
||||
font-size: var(--font-base-size);
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
|
|
|
@ -3,14 +3,43 @@
|
|||
<ul class="poll-list">
|
||||
<li class="poll-option" v-for="(option, id) in value" v-bind:key="id">
|
||||
<el-radio :disabled="true" :label="id">
|
||||
<el-input :placeholder="`choice ${id}`" :value="value[id]" @input="value => updateOption(value, id)" size="small"></el-input>
|
||||
<el-button class="remove-poll" type="text" @click="removePoll(id)" size="small"><font-awesome-icon icon="xmark" /></el-button>
|
||||
<el-input
|
||||
:placeholder="`choice ${id}`"
|
||||
:model-value="value[id]"
|
||||
@input="(value) => updateOption(value, id)"
|
||||
size="small"
|
||||
></el-input>
|
||||
<el-button
|
||||
class="remove-poll"
|
||||
type="text"
|
||||
@click="removePoll(id)"
|
||||
size="small"
|
||||
><font-awesome-icon icon="xmark"
|
||||
/></el-button>
|
||||
</el-radio>
|
||||
</li>
|
||||
</ul>
|
||||
<el-button class="add-poll" type="info" size="small" @click="addPoll" plain>{{ $t('modals.new_toot.poll.add_choice') }}</el-button>
|
||||
<el-select v-model="expiresIn" size="small" value-key="value" @change="changeExpire">
|
||||
<el-option v-for="exp in expires" :key="exp.value" :label="exp.label" :value="exp"> </el-option>
|
||||
<el-button
|
||||
class="add-poll"
|
||||
type="info"
|
||||
size="small"
|
||||
@click="addPoll"
|
||||
plain
|
||||
>{{ $t('modals.new_toot.poll.add_choice') }}</el-button
|
||||
>
|
||||
<el-select
|
||||
v-model="expiresIn"
|
||||
size="small"
|
||||
value-key="value"
|
||||
@change="changeExpire"
|
||||
>
|
||||
<el-option
|
||||
v-for="exp in expires"
|
||||
:key="exp.value"
|
||||
:label="exp.label"
|
||||
:value="exp"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -24,34 +53,34 @@ export default {
|
|||
expires: [
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.5_minutes'),
|
||||
value: 60 * 5
|
||||
value: 60 * 5,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.30_minutes'),
|
||||
value: 60 * 30
|
||||
value: 60 * 30,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.1_hour'),
|
||||
value: 3600
|
||||
value: 3600,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.6_hours'),
|
||||
value: 3600 * 6
|
||||
value: 3600 * 6,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
value: 3600 * 24,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.3_days'),
|
||||
value: 3600 * 24 * 3
|
||||
value: 3600 * 24 * 3,
|
||||
},
|
||||
{
|
||||
label: this.$t('modals.new_toot.poll.expires.7_days'),
|
||||
value: 3600 * 24 * 7
|
||||
}
|
||||
value: 3600 * 24 * 7,
|
||||
},
|
||||
],
|
||||
expiresIn: null
|
||||
expiresIn: null,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -65,13 +94,17 @@ export default {
|
|||
this.$emit('removePoll', id)
|
||||
},
|
||||
updateOption(item, index) {
|
||||
const newValue = [...this.value.slice(0, index), item, ...this.value.slice(index + 1)]
|
||||
const newValue = [
|
||||
...this.value.slice(0, index),
|
||||
item,
|
||||
...this.value.slice(index + 1),
|
||||
]
|
||||
this.$emit('input', newValue)
|
||||
},
|
||||
changeExpire(exp) {
|
||||
this.$emit('changeExpire', exp)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -6,14 +6,22 @@
|
|||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
<div class="user">
|
||||
<span class="display-name"><bdi v-html="username(message.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(message.account)"></bdi
|
||||
></span>
|
||||
<span class="acct">{{ accountName(message.account) }}</span>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="content-wrapper">
|
||||
<div class="spoiler" v-html="emojiText(message.spoiler_text, message.emojis)"></div>
|
||||
<div class="content" v-html="emojiText(message.content, message.emojis)"></div>
|
||||
<div
|
||||
class="spoiler"
|
||||
v-html="emojiText(message.spoiler_text, message.emojis)"
|
||||
></div>
|
||||
<div
|
||||
class="content"
|
||||
v-html="emojiText(message.content, message.emojis)"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -28,17 +36,17 @@ import emojify from '@/utils/emojify'
|
|||
export default {
|
||||
new: 'quote-target',
|
||||
components: {
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
displayNameStyle: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -70,8 +78,8 @@ export default {
|
|||
},
|
||||
emojiText(content, emojis) {
|
||||
return emojify(content, emojis)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -5,8 +5,18 @@
|
|||
ref="status"
|
||||
v-shortkey="
|
||||
openSuggest
|
||||
? { up: ['arrowup'], down: ['arrowdown'], enter: ['enter'], esc: ['esc'] }
|
||||
: { linux: ['ctrl', 'enter'], mac: ['meta', 'enter'], left: ['arrowleft'], right: ['arrowright'] }
|
||||
? {
|
||||
up: ['arrowup'],
|
||||
down: ['arrowdown'],
|
||||
enter: ['enter'],
|
||||
esc: ['esc'],
|
||||
}
|
||||
: {
|
||||
linux: ['ctrl', 'enter'],
|
||||
mac: ['meta', 'enter'],
|
||||
left: ['arrowleft'],
|
||||
right: ['arrowright'],
|
||||
}
|
||||
"
|
||||
@shortkey="handleKey"
|
||||
@paste="onPaste"
|
||||
|
@ -19,7 +29,13 @@
|
|||
autofocus
|
||||
>
|
||||
</textarea>
|
||||
<el-popover placement="bottom-start" width="300" trigger="manual" :value="openSuggest" popper-class="suggest-popper">
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
width="300"
|
||||
trigger="manual"
|
||||
:model-value="openSuggest"
|
||||
popper-class="suggest-popper"
|
||||
>
|
||||
<ul class="suggest-list">
|
||||
<li
|
||||
v-for="(item, index) in filteredSuggestion"
|
||||
|
@ -44,7 +60,12 @@
|
|||
<font-awesome-icon :icon="['far', 'face-smile']" size="lg" />
|
||||
</el-button>
|
||||
<div v-if="openEmojiPicker" class="emoji-picker">
|
||||
<picker set="emojione" :autoFocus="true" :custom="pickerEmojis" @select="selectEmoji" />
|
||||
<picker
|
||||
set="emojione"
|
||||
:autoFocus="true"
|
||||
:custom="pickerEmojis"
|
||||
@select="selectEmoji"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -59,42 +80,42 @@ import suggestText from '@/utils/suggestText'
|
|||
export default {
|
||||
name: 'status',
|
||||
directives: {
|
||||
ClickOutside
|
||||
ClickOutside,
|
||||
},
|
||||
components: {
|
||||
Picker
|
||||
Picker,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
opened: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
fixCursorPos: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 120
|
||||
}
|
||||
default: 120,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
highlightedIndex: 0,
|
||||
openEmojiPicker: false
|
||||
openEmojiPicker: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/NewToot/Status', {
|
||||
filteredAccounts: state => state.filteredAccounts,
|
||||
filteredHashtags: state => state.filteredHashtags,
|
||||
openSuggest: state => state.openSuggest,
|
||||
startIndex: state => state.startIndex,
|
||||
matchWord: state => state.matchWord,
|
||||
filteredSuggestion: state => state.filteredSuggestion
|
||||
filteredAccounts: (state) => state.filteredAccounts,
|
||||
filteredHashtags: (state) => state.filteredHashtags,
|
||||
openSuggest: (state) => state.openSuggest,
|
||||
startIndex: (state) => state.startIndex,
|
||||
matchWord: (state) => state.matchWord,
|
||||
filteredSuggestion: (state) => state.filteredSuggestion,
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals/NewToot/Status', ['pickerEmojis']),
|
||||
status: {
|
||||
|
@ -103,8 +124,8 @@ export default {
|
|||
},
|
||||
set: function (value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// When change account, the new toot modal is recreated.
|
||||
|
@ -127,7 +148,7 @@ export default {
|
|||
this.closeSuggest()
|
||||
this.hideEmojiPicker()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async startSuggest(e) {
|
||||
|
@ -163,7 +184,10 @@ export default {
|
|||
},
|
||||
async suggestAccount(start, word) {
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestAccount', { word: word, start: start })
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/Status/suggestAccount',
|
||||
{ word: word, start: start }
|
||||
)
|
||||
this.$emit('suggestOpened', true)
|
||||
return true
|
||||
} catch (err) {
|
||||
|
@ -173,7 +197,10 @@ export default {
|
|||
},
|
||||
async suggestHashtag(start, word) {
|
||||
try {
|
||||
await this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestHashtag', { word: word, start: start })
|
||||
await this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/Status/suggestHashtag',
|
||||
{ word: word, start: start }
|
||||
)
|
||||
this.$emit('suggestOpened', true)
|
||||
return true
|
||||
} catch (err) {
|
||||
|
@ -183,7 +210,10 @@ export default {
|
|||
},
|
||||
suggestEmoji(start, word) {
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/Status/suggestEmoji', { word: word, start: start })
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/Status/suggestEmoji',
|
||||
{ word: word, start: start }
|
||||
)
|
||||
this.$emit('suggestOpened', true)
|
||||
return true
|
||||
} catch (err) {
|
||||
|
@ -209,10 +239,14 @@ export default {
|
|||
},
|
||||
insertItem(item) {
|
||||
if (item.code) {
|
||||
const str = `${this.status.slice(0, this.startIndex - 1)}${item.code} ${this.status.slice(this.startIndex + this.matchWord.length)}`
|
||||
const str = `${this.status.slice(0, this.startIndex - 1)}${
|
||||
item.code
|
||||
} ${this.status.slice(this.startIndex + this.matchWord.length)}`
|
||||
this.status = str
|
||||
} else {
|
||||
const str = `${this.status.slice(0, this.startIndex - 1)}${item.name} ${this.status.slice(this.startIndex + this.matchWord.length)}`
|
||||
const str = `${this.status.slice(0, this.startIndex - 1)}${
|
||||
item.name
|
||||
} ${this.status.slice(this.startIndex + this.matchWord.length)}`
|
||||
this.status = str
|
||||
}
|
||||
this.closeSuggest()
|
||||
|
@ -266,14 +300,18 @@ export default {
|
|||
selectEmoji(emoji) {
|
||||
const current = this.$refs.status.selectionStart
|
||||
if (emoji.native) {
|
||||
this.status = `${this.status.slice(0, current)}${emoji.native} ${this.status.slice(current)}`
|
||||
this.status = `${this.status.slice(0, current)}${
|
||||
emoji.native
|
||||
} ${this.status.slice(current)}`
|
||||
} else {
|
||||
// Custom emoji don't have natvie code
|
||||
this.status = `${this.status.slice(0, current)}${emoji.name} ${this.status.slice(current)}`
|
||||
this.status = `${this.status.slice(0, current)}${
|
||||
emoji.name
|
||||
} ${this.status.slice(current)}`
|
||||
}
|
||||
this.hideEmojiPicker()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="$t('modals.report.title')"
|
||||
:visible.sync="reportModal"
|
||||
width="400px"
|
||||
custom-class="report"
|
||||
<el-dialog
|
||||
:title="$t('modals.report.title')"
|
||||
:visible.sync="reportModal"
|
||||
width="400px"
|
||||
custom-class="report"
|
||||
>
|
||||
<el-input type="textarea" v-model="comment" :placeholder="$t('modals.report.comment')"></el-input>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeModal">{{ $t('modals.report.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ $t('modals.report.ok') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="comment"
|
||||
:placeholder="$t('modals.report.comment')"
|
||||
></el-input>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeModal">{{
|
||||
$t('modals.report.cancel')
|
||||
}}</el-button>
|
||||
<el-button type="primary" @click="submit">{{
|
||||
$t('modals.report.ok')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -18,39 +26,38 @@ import { mapState } from 'vuex'
|
|||
|
||||
export default {
|
||||
name: 'Report',
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
comment: ''
|
||||
comment: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/Report', {
|
||||
toot: state => state.message
|
||||
toot: (state) => state.message,
|
||||
}),
|
||||
reportModal: {
|
||||
get () {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.Report.modalOpen
|
||||
},
|
||||
set (value) {
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/Report/changeModalOpen', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeModal () {
|
||||
closeModal() {
|
||||
this.reportModal = false
|
||||
},
|
||||
async submit () {
|
||||
async submit() {
|
||||
this.closeModal()
|
||||
await this.$store.dispatch('TimelineSpace/Modals/Report/submit', {
|
||||
account_id: this.toot.account.id,
|
||||
status_id: this.toot.id,
|
||||
comment: this.comment
|
||||
comment: this.comment,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<template>
|
||||
<el-dialog :title="$t('modals.shortcut.title')" :visible.sync="shortcutModal" width="500px" class="shortcut-modal">
|
||||
<el-dialog
|
||||
:title="$t('modals.shortcut.title')"
|
||||
:visible.sync="shortcutModal"
|
||||
width="500px"
|
||||
class="shortcut-modal"
|
||||
>
|
||||
<table class="shortcuts">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -89,9 +94,9 @@ export default {
|
|||
},
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/Shortcut/changeModal', value)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div id="receive_drop">
|
||||
<div class="drop-area">
|
||||
<div class="drop-message">
|
||||
<h1>{{ $t('receive_drop.drop_message') }}</h1>
|
||||
<div id="receive_drop">
|
||||
<div class="drop-area">
|
||||
<div class="drop-message">
|
||||
<h1>{{ $t('receive_drop.drop_message') }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'receive-drop'
|
||||
name: 'receive-drop',
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div id="side_menu">
|
||||
<div :class="collapse ? 'profile-wrapper narrow-menu' : 'profile-wrapper'" style="-webkit-app-region: drag">
|
||||
<div
|
||||
:class="collapse ? 'profile-wrapper narrow-menu' : 'profile-wrapper'"
|
||||
style="-webkit-app-region: drag"
|
||||
>
|
||||
<div :class="collapse ? 'profile-narrow' : 'profile-wide'">
|
||||
<div class="account">
|
||||
<div class="avatar" v-if="collapse">
|
||||
|
@ -10,23 +13,45 @@
|
|||
@{{ account.username }}
|
||||
<span class="domain-name">{{ account.domain }}</span>
|
||||
</div>
|
||||
<el-dropdown trigger="click" @command="handleProfile" :title="$t('side_menu.profile')">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="handleProfile"
|
||||
:title="$t('side_menu.profile')"
|
||||
>
|
||||
<span class="el-dropdown-link">
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
<el-icon class="el-icon--right"><el-icon-arrow-down /></el-icon>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="show">{{ $t('side_menu.show_profile') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="edit">{{ $t('side_menu.edit_profile') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="settings">{{ $t('side_menu.settings') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="show">{{
|
||||
$t('side_menu.show_profile')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item command="edit">{{
|
||||
$t('side_menu.edit_profile')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item command="settings">{{
|
||||
$t('side_menu.settings')
|
||||
}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse">
|
||||
<el-button type="text" class="release-collapse" @click="releaseCollapse" v-if="collapse" :title="$t('side_menu.expand')">
|
||||
<el-button
|
||||
type="text"
|
||||
class="release-collapse"
|
||||
@click="releaseCollapse"
|
||||
v-if="collapse"
|
||||
:title="$t('side_menu.expand')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fa', 'angles-right']" />
|
||||
</el-button>
|
||||
<el-button type="text" class="do-collapse" @click="doCollapse" v-else :title="$t('side_menu.collapse')">
|
||||
<el-button
|
||||
type="text"
|
||||
class="do-collapse"
|
||||
@click="doCollapse"
|
||||
v-else
|
||||
:title="$t('side_menu.collapse')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fa', 'angles-left']" />
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -38,10 +63,19 @@
|
|||
:collapse="collapse"
|
||||
active-text-color="#ffffff"
|
||||
:router="true"
|
||||
:class="collapse ? 'el-menu-vertical timeline-menu narrow-menu' : 'el-menu-vertical timeline-menu'"
|
||||
:class="
|
||||
collapse
|
||||
? 'el-menu-vertical timeline-menu narrow-menu'
|
||||
: 'el-menu-vertical timeline-menu'
|
||||
"
|
||||
role="menu"
|
||||
>
|
||||
<el-menu-item :index="`/${id()}/home`" role="menuitem" :title="$t('side_menu.home')" class="menu-item">
|
||||
<el-menu-item
|
||||
:index="`/${id()}/home`"
|
||||
role="menuitem"
|
||||
:title="$t('side_menu.home')"
|
||||
class="menu-item"
|
||||
>
|
||||
<div class="menu-item-icon">
|
||||
<font-awesome-icon icon="home" />
|
||||
</div>
|
||||
|
@ -168,7 +202,12 @@
|
|||
<el-badge is-dot :hidden="!unreadPublicTimeline"> </el-badge>
|
||||
</div>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="`/${id()}/search`" role="menuitem" :title="$t('side_menu.search')" class="menu-item">
|
||||
<el-menu-item
|
||||
:index="`/${id()}/search`"
|
||||
role="menuitem"
|
||||
:title="$t('side_menu.search')"
|
||||
class="menu-item"
|
||||
>
|
||||
<div class="menu-item-icon">
|
||||
<font-awesome-icon icon="magnifying-glass" />
|
||||
</div>
|
||||
|
@ -176,7 +215,12 @@
|
|||
<span>{{ $t('side_menu.search') }}</span>
|
||||
</div>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="`/${id()}/hashtag`" role="menuitem" :title="$t('side_menu.hashtag')" class="menu-item">
|
||||
<el-menu-item
|
||||
:index="`/${id()}/hashtag`"
|
||||
role="menuitem"
|
||||
:title="$t('side_menu.hashtag')"
|
||||
class="menu-item"
|
||||
>
|
||||
<div class="menu-item-icon">
|
||||
<font-awesome-icon icon="hashtag" />
|
||||
</div>
|
||||
|
@ -201,7 +245,12 @@
|
|||
</div>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
<el-menu-item :index="`/${id()}/lists`" role="menuitem" :title="$t('side_menu.lists')" class="menu-item">
|
||||
<el-menu-item
|
||||
:index="`/${id()}/lists`"
|
||||
role="menuitem"
|
||||
:title="$t('side_menu.lists')"
|
||||
class="menu-item"
|
||||
>
|
||||
<div class="menu-item-icon">
|
||||
<font-awesome-icon icon="list-ul" />
|
||||
</div>
|
||||
|
@ -227,39 +276,54 @@
|
|||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
<el-button v-if="hideGlobalHeader" class="global-header-control" type="text" @click="changeGlobalHeader(false)">
|
||||
<el-button
|
||||
v-if="hideGlobalHeader"
|
||||
class="global-header-control"
|
||||
type="text"
|
||||
@click="changeGlobalHeader(false)"
|
||||
>
|
||||
<font-awesome-icon icon="angles-right" />
|
||||
</el-button>
|
||||
<el-button v-else class="global-header-control" type="text" @click="changeGlobalHeader(true)">
|
||||
<el-button
|
||||
v-else
|
||||
class="global-header-control"
|
||||
type="text"
|
||||
@click="changeGlobalHeader(true)"
|
||||
>
|
||||
<font-awesome-icon icon="angles-left" />
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown as ElIconArrowDown } from '@element-plus/icons'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ElIconArrowDown,
|
||||
},
|
||||
name: 'side-menu',
|
||||
computed: {
|
||||
...mapState('TimelineSpace/SideMenu', {
|
||||
unreadHomeTimeline: state => state.unreadHomeTimeline,
|
||||
unreadNotifications: state => state.unreadNotifications,
|
||||
unreadMentions: state => state.unreadMentions,
|
||||
unreadLocalTimeline: state => state.unreadLocalTimeline,
|
||||
unreadDirectMessagesTimeline: state => state.unreadDirectMessagesTimeline,
|
||||
unreadPublicTimeline: state => state.unreadPublicTimeline,
|
||||
unreadFollowRequests: state => state.unreadFollowRequests,
|
||||
lists: state => state.lists,
|
||||
tags: state => state.tags,
|
||||
collapse: state => state.collapse,
|
||||
enabledTimelines: state => state.enabledTimelines
|
||||
unreadHomeTimeline: (state) => state.unreadHomeTimeline,
|
||||
unreadNotifications: (state) => state.unreadNotifications,
|
||||
unreadMentions: (state) => state.unreadMentions,
|
||||
unreadLocalTimeline: (state) => state.unreadLocalTimeline,
|
||||
unreadDirectMessagesTimeline: (state) =>
|
||||
state.unreadDirectMessagesTimeline,
|
||||
unreadPublicTimeline: (state) => state.unreadPublicTimeline,
|
||||
unreadFollowRequests: (state) => state.unreadFollowRequests,
|
||||
lists: (state) => state.lists,
|
||||
tags: (state) => state.tags,
|
||||
collapse: (state) => state.collapse,
|
||||
enabledTimelines: (state) => state.enabledTimelines,
|
||||
}),
|
||||
...mapState({
|
||||
account: state => state.TimelineSpace.account,
|
||||
themeColor: state => state.App.theme.side_menu_color,
|
||||
hideGlobalHeader: state => state.GlobalHeader.hide
|
||||
})
|
||||
account: (state) => state.TimelineSpace.account,
|
||||
themeColor: (state) => state.App.theme.side_menu_color,
|
||||
hideGlobalHeader: (state) => state.GlobalHeader.hide,
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('TimelineSpace/SideMenu/readCollapse')
|
||||
|
@ -275,12 +339,25 @@ export default {
|
|||
handleProfile(command) {
|
||||
switch (command) {
|
||||
case 'show':
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/fetchAccount', this.account.accountId).then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
})
|
||||
this.$store
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/fetchAccount',
|
||||
this.account.accountId
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
break
|
||||
case 'edit':
|
||||
window.shell.openExternal(this.account.baseURL + '/settings/profile')
|
||||
|
@ -300,8 +377,8 @@ export default {
|
|||
},
|
||||
async changeGlobalHeader(value) {
|
||||
await this.$store.dispatch('GlobalHeader/switchHide', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -18,30 +18,30 @@ export default {
|
|||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
alt: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
readExif: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
failoverSrc: {
|
||||
type: String,
|
||||
default:
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACvtJREFUeNrs3WtrFEkbgOGsCS4GBEVREBIUAgFBQfD//4EIQgQhoCQkICgGhUDEQGAfLN6i3p6ZPsXp6Z5c14dl3cQ5dPfdVX2Y2X8ODg42gNW5YxGACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEIg21rS425ubm5vb4/qrV5fX19eXlrl3JYIo8D9/f1RvdWLi4ujoyOrHNNRQIQgQmDpx4QVqzoY29nZGdv5IVhNhBcXFyt5e9fX19YxpqOACEGEwIqPCee6f//+06dP45+bm5tx0Hh+fv79+3erBBEOZGdnJwosgwx379798uXLbVsH8ca3t7djT5T+GPujy8tLp5SydAtkLKX0x3T74apO9a1PhA8ePCgLDNHe169fx7nlxUuNXUZ+nY27ib29vXiD8S8/f/789OnTol/7999/nz179ujRo7k/jXlBPNHv3797vODYZF++fJn+/ezsLBbsop/GsxwfH7eP4fXr12ln0fIewPKvXF1dHR4e9pgrpYVZEZtKLN76RfTmzZu8a2sjHvP9+/e3JcLd3d3yjycnJ2OeiJYrMraJ2HDr28i/X7MFPH78OMKu+YVHf/RbMuXDzj5F+V9i+44/ttz3xWvutE2Hhw8f5r8S05yIqv0IVpkrzb6LWD7x+mMvs2gRdX21XX9/widmYgSI9VHu8id0KBjr6fnz5zd8kNia40HarPL4tfjlpb6dmg19dkbQY8pTeeN/pcDK6ljqIlrPkbAsMPz48WNyh3CxbcVcqPc+KE9u0xQopovxaOljVungJ6apOdHYyC7/WNLbiS24zXF4vOXKimtTSCXCuRPLxqOVmMfGK4whNE1AYhGlX8iLKJZn/ulc8QhtdvSrOhpaQYSVCckUj7BjOh0vu986KwOLjSOOrMqtJ/UWW8z+/n6+4S42suXd9xdpRYeN22iPYXB2gEpZNu6/yqOVWM5xXF0u6rSIYs+VF1E8bCyimsPvWMJjPuG3muuEZXgxMkwuwthwe2yU+Ugm/zG2m7n779jmPn/+XI69S11KT548aRy988nJ9vI7LROKo8TGs0p5yI2dVKXAyiLKP5r0x7VXE2EcTJcLfULLK6/1GNB6hFFuynkKumjnHUfLXSdy/ZQXABaN3j1m3XnNxjCb32mUWX8wXL7T+hPmsYiOj49jKX348GHSV7ZWE2GskryHK6dn41ee7u9xhqbc4zTOysqj5WXvqhrPQ/YeBjf+nHv79u1by8Gwsp+qf5b4heiw34Wc2x5hWnyHh4cxJEaQ/aZ2KxF73LxTT2doekfYuOmUk/auJ0VaivleHn8WDezl2ml/AJ8PCOMpYomVO5T6hVbukade19gj3PjficEYEqc1lyjn0ru7u52G8fKXGw9jBjhZVw7si+acOaeLP1rua/JeI+WXrq3nCGsWWt5PrdM9MeONcKLSba43PEPTtbElTUfL+7/mthEF5pzKY9ROc9HZueXUr+z9XVtTfwPpa91i6+l0B9YNnZ6e5k02BpDGe2huMl1MDSzvsDmmIel78dKF+8qsJOeULrW1PEOTGyuvcMaQmI+i42ErN9MteyNpfOUrvGtyaz0KzJvLMB3G2oqNNV9zj21rSdfxou0lHQ2WA3tOvXLhPt1Vn1tt+YDliFoOnmlGmg4IY8XFIWiPPVc5Ms+O6otO5MTraYyw/WRbhPMLLHfbw3QYO854ujRLvOE9NCsXgaUxqnLhPg9o0U/7G5vKk5+VZZIjTK32GAxjmS+6mhIJTXQV3FmbAvNKevHixTCv4eTkpPcZmlGJ6vJMLF+4j5Eqz0XbT9XKW9ViaKqMdeUTjeqUeLyqfKLYSHijAgceD9PNU2ljSmdo/vpp3h73qfQe2NOELV24j1Fl7smVNsPg3LloORimR44lFs/V9U6X2Rljm0U08i9fX32EseNMK6PlXKK+wNxhKmSAiVz+gE9sxPU3wdww+GVHmG+Jjn+JrTaPVJ1OO5XXAOeu0JjW5rzTauq6wCv/5e3btxsTt+II04d68uyu8TbiNgXmedEw05izs7P8Fjrdad3pzMSyT9ylsyYpjwipvI2p/fBe+djEq1evGofN8qLr7PLptJane13xzkgK3Gjx2bn2BQ58QJVXf0yN6t9CeeDReNpz4Ltqy9jyucT6jwjNrtBOz5g+5rtowtnmtPB6fLPznZEU2NjhOAtMyt15/eflyw268WCm3MIG+JRA5ZbxrsPgxv9fo+/dbTnmNzY28CJaq+no3AJzh2l4mUqBafXHxppGj/r/MWM5ZWr8NG25Tf/69WuYUb180k7fp1R+bKLxCD9f7pu9jzSeMf/HOC6tP8E2/CJakwhrCpzb4cgLzCc2aq4jl1tYvjKeTqguOnsUG2L5/WLDfP9AumCdn7f86EOnYTB2LvUR5q/VmP2Yb/x7vgsi3VizaIiLRyizn+7d3nfGVmBlXjqJAlMnp6enLUebcu4693JZbJfl1c4h76jKO4X0Af8eE8vyXu1Fynlv5ZNNlVlxrP258/byK/C67i9u9UjYssDcYf3x1djEllcOIzXnP9JVmbLD/LHX9AUq5YQ2Rs4hb7OMd/Hu3buuf6v82ESbS03xZvOMIIa72H+Ve5m0iNKqj39Gh2mIjr+1tbV179696LacdMSP6vcXsVLa/H+j4zXUfEfGOkTYqcA8aZnWLu3k5KTxvHz6tXJ4j+1p0Z2NabMY/xcBl3PRljPn2LPkoSyiKitKH5nf29srK1q0d0sfEG98usFuexj1dLScPKyrll8oFNvN4eFh4zmP+LWjo6NJnPQrP8Lb8qaL8tdmT8/ETz9+/Nh4K1n8WiyiqX9b+XAj4XRvrYw1nfajbVZ27ODzd9rXZBYPFVtPuq5Y+SBf/Cjdi9z761hj281PPZtE+dOuN0zm86XlW4sXn/cU7W+hTsd+Naey0q4qLZ9Kpekt1JyzyUeenT6DsqqY/zk4OFjG41Zm4XGYMfDtRen76svD+pHfQJhe5+35OHm/RZT+RxRr9r62rNqRkN+tXUS+3gJECCIcxpAXu8zucEw4x9nZ2fn5+TDnSK+urm7JV1YiwrYGvlR694+NKV8XQYR/WZubhsAxISBCMB39W9K9V6N6q+t3pwUibNjix3yPGJiOAiIEEQIiBBGCCC0CECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBDG6D8BBgBNIRvwsstoqwAAAABJRU5ErkJggg=='
|
||||
}
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACvtJREFUeNrs3WtrFEkbgOGsCS4GBEVREBIUAgFBQfD//4EIQgQhoCQkICgGhUDEQGAfLN6i3p6ZPsXp6Z5c14dl3cQ5dPfdVX2Y2X8ODg42gNW5YxGACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhIAIQYSACEGEgAhBhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEJAhCBCQIQgQkCEIEIg21rS425ubm5vb4/qrV5fX19eXlrl3JYIo8D9/f1RvdWLi4ujoyOrHNNRQIQgQmDpx4QVqzoY29nZGdv5IVhNhBcXFyt5e9fX19YxpqOACEGEwIqPCee6f//+06dP45+bm5tx0Hh+fv79+3erBBEOZGdnJwosgwx379798uXLbVsH8ca3t7djT5T+GPujy8tLp5SydAtkLKX0x3T74apO9a1PhA8ePCgLDNHe169fx7nlxUuNXUZ+nY27ib29vXiD8S8/f/789OnTol/7999/nz179ujRo7k/jXlBPNHv3797vODYZF++fJn+/ezsLBbsop/GsxwfH7eP4fXr12ln0fIewPKvXF1dHR4e9pgrpYVZEZtKLN76RfTmzZu8a2sjHvP9+/e3JcLd3d3yjycnJ2OeiJYrMraJ2HDr28i/X7MFPH78OMKu+YVHf/RbMuXDzj5F+V9i+44/ttz3xWvutE2Hhw8f5r8S05yIqv0IVpkrzb6LWD7x+mMvs2gRdX21XX9/widmYgSI9VHu8id0KBjr6fnz5zd8kNia40HarPL4tfjlpb6dmg19dkbQY8pTeeN/pcDK6ljqIlrPkbAsMPz48WNyh3CxbcVcqPc+KE9u0xQopovxaOljVungJ6apOdHYyC7/WNLbiS24zXF4vOXKimtTSCXCuRPLxqOVmMfGK4whNE1AYhGlX8iLKJZn/ulc8QhtdvSrOhpaQYSVCckUj7BjOh0vu986KwOLjSOOrMqtJ/UWW8z+/n6+4S42suXd9xdpRYeN22iPYXB2gEpZNu6/yqOVWM5xXF0u6rSIYs+VF1E8bCyimsPvWMJjPuG3muuEZXgxMkwuwthwe2yU+Ugm/zG2m7n779jmPn/+XI69S11KT548aRy988nJ9vI7LROKo8TGs0p5yI2dVKXAyiLKP5r0x7VXE2EcTJcLfULLK6/1GNB6hFFuynkKumjnHUfLXSdy/ZQXABaN3j1m3XnNxjCb32mUWX8wXL7T+hPmsYiOj49jKX348GHSV7ZWE2GskryHK6dn41ee7u9xhqbc4zTOysqj5WXvqhrPQ/YeBjf+nHv79u1by8Gwsp+qf5b4heiw34Wc2x5hWnyHh4cxJEaQ/aZ2KxF73LxTT2doekfYuOmUk/auJ0VaivleHn8WDezl2ml/AJ8PCOMpYomVO5T6hVbukade19gj3PjficEYEqc1lyjn0ru7u52G8fKXGw9jBjhZVw7si+acOaeLP1rua/JeI+WXrq3nCGsWWt5PrdM9MeONcKLSba43PEPTtbElTUfL+7/mthEF5pzKY9ROc9HZueXUr+z9XVtTfwPpa91i6+l0B9YNnZ6e5k02BpDGe2huMl1MDSzvsDmmIel78dKF+8qsJOeULrW1PEOTGyuvcMaQmI+i42ErN9MteyNpfOUrvGtyaz0KzJvLMB3G2oqNNV9zj21rSdfxou0lHQ2WA3tOvXLhPt1Vn1tt+YDliFoOnmlGmg4IY8XFIWiPPVc5Ms+O6otO5MTraYyw/WRbhPMLLHfbw3QYO854ujRLvOE9NCsXgaUxqnLhPg9o0U/7G5vKk5+VZZIjTK32GAxjmS+6mhIJTXQV3FmbAvNKevHixTCv4eTkpPcZmlGJ6vJMLF+4j5Eqz0XbT9XKW9ViaKqMdeUTjeqUeLyqfKLYSHijAgceD9PNU2ljSmdo/vpp3h73qfQe2NOELV24j1Fl7smVNsPg3LloORimR44lFs/V9U6X2Rljm0U08i9fX32EseNMK6PlXKK+wNxhKmSAiVz+gE9sxPU3wdww+GVHmG+Jjn+JrTaPVJ1OO5XXAOeu0JjW5rzTauq6wCv/5e3btxsTt+II04d68uyu8TbiNgXmedEw05izs7P8Fjrdad3pzMSyT9ylsyYpjwipvI2p/fBe+djEq1evGofN8qLr7PLptJane13xzkgK3Gjx2bn2BQ58QJVXf0yN6t9CeeDReNpz4Ltqy9jyucT6jwjNrtBOz5g+5rtowtnmtPB6fLPznZEU2NjhOAtMyt15/eflyw268WCm3MIG+JRA5ZbxrsPgxv9fo+/dbTnmNzY28CJaq+no3AJzh2l4mUqBafXHxppGj/r/MWM5ZWr8NG25Tf/69WuYUb180k7fp1R+bKLxCD9f7pu9jzSeMf/HOC6tP8E2/CJakwhrCpzb4cgLzCc2aq4jl1tYvjKeTqguOnsUG2L5/WLDfP9AumCdn7f86EOnYTB2LvUR5q/VmP2Yb/x7vgsi3VizaIiLRyizn+7d3nfGVmBlXjqJAlMnp6enLUebcu4693JZbJfl1c4h76jKO4X0Af8eE8vyXu1Fynlv5ZNNlVlxrP258/byK/C67i9u9UjYssDcYf3x1djEllcOIzXnP9JVmbLD/LHX9AUq5YQ2Rs4hb7OMd/Hu3buuf6v82ESbS03xZvOMIIa72H+Ve5m0iNKqj39Gh2mIjr+1tbV179696LacdMSP6vcXsVLa/H+j4zXUfEfGOkTYqcA8aZnWLu3k5KTxvHz6tXJ4j+1p0Z2NabMY/xcBl3PRljPn2LPkoSyiKitKH5nf29srK1q0d0sfEG98usFuexj1dLScPKyrll8oFNvN4eFh4zmP+LWjo6NJnPQrP8Lb8qaL8tdmT8/ETz9+/Nh4K1n8WiyiqX9b+XAj4XRvrYw1nfajbVZ27ODzd9rXZBYPFVtPuq5Y+SBf/Cjdi9z761hj281PPZtE+dOuN0zm86XlW4sXn/cU7W+hTsd+Naey0q4qLZ9Kpekt1JyzyUeenT6DsqqY/zk4OFjG41Zm4XGYMfDtRen76svD+pHfQJhe5+35OHm/RZT+RxRr9r62rNqRkN+tXUS+3gJECCIcxpAXu8zucEw4x9nZ2fn5+TDnSK+urm7JV1YiwrYGvlR694+NKV8XQYR/WZubhsAxISBCMB39W9K9V6N6q+t3pwUibNjix3yPGJiOAiIEEQIiBBGCCC0CECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBDG6D8BBgBNIRvwsstoqwAAAABJRU5ErkJggg==',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
originalSrc: this.src
|
||||
originalSrc: this.src,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
@ -55,7 +55,7 @@ export default {
|
|||
}
|
||||
},
|
||||
watch: {
|
||||
src: async function(newSrc, _oldSrc) {
|
||||
src: async function (newSrc, _oldSrc) {
|
||||
this.originalSrc = newSrc
|
||||
if (this.readExif) {
|
||||
try {
|
||||
|
@ -65,13 +65,13 @@ export default {
|
|||
console.warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
failover() {
|
||||
this.originalSrc = this.failoverSrc
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,20 +3,22 @@ export default {
|
|||
name: 'reloadable',
|
||||
methods: {
|
||||
async reloadable() {
|
||||
const account = await this.$store.dispatch('TimelineSpace/localAccount', this.$route.params.id).catch(err => {
|
||||
this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error'
|
||||
const account = await this.$store
|
||||
.dispatch('TimelineSpace/localAccount', this.$route.params.id)
|
||||
.catch((err) => {
|
||||
this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error',
|
||||
})
|
||||
throw err
|
||||
})
|
||||
throw err
|
||||
})
|
||||
await this.$store.dispatch('GlobalHeader/stopUserStreamings')
|
||||
await this.$store.dispatch('TimelineSpace/stopStreamings')
|
||||
await this.$store.dispatch('TimelineSpace/fetchContentsTimelines')
|
||||
await this.$store.dispatch('TimelineSpace/startStreamings')
|
||||
this.$store.dispatch('GlobalHeader/startUserStreamings')
|
||||
return account
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -15,8 +15,8 @@ export default {
|
|||
props: {
|
||||
tag: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openTag(tag) {
|
||||
|
@ -24,8 +24,8 @@ export default {
|
|||
},
|
||||
id() {
|
||||
return this.$route.params.id
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="link" @click="openLink(url)">
|
||||
<el-image :src="icon" class="icon" fit="cover" lazy>
|
||||
<div class="image-slot" slot="error">
|
||||
<i class="el-icon-link"></i>
|
||||
<el-icon><el-icon-link /></el-icon>
|
||||
</div>
|
||||
</el-image>
|
||||
<div class="contents">
|
||||
|
@ -13,33 +13,37 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Link as ElIconLink } from '@element-plus/icons'
|
||||
export default {
|
||||
components: {
|
||||
ElIconLink,
|
||||
},
|
||||
name: 'link-preview',
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openLink(link) {
|
||||
if (link) {
|
||||
return window.shell.openExternal(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,25 +3,51 @@
|
|||
<template v-if="poll">
|
||||
<ul class="poll-list">
|
||||
<template v-if="poll.voted">
|
||||
<li class="voted" v-for="(option, id) in poll.options" v-bind:key="id">
|
||||
<span class="progress-bar" :style="progress(percentage(option.votes_count, poll.votes_count))"></span>
|
||||
<li
|
||||
class="voted"
|
||||
v-for="(option, id) in poll.options"
|
||||
v-bind:key="id"
|
||||
>
|
||||
<span
|
||||
class="progress-bar"
|
||||
:style="
|
||||
progress(percentage(option.votes_count, poll.votes_count))
|
||||
"
|
||||
></span>
|
||||
<label class="text">
|
||||
<span class="percentage">{{ percentage(option.votes_count, poll.votes_count) }}%</span>
|
||||
<span class="percentage"
|
||||
>{{ percentage(option.votes_count, poll.votes_count) }}%</span
|
||||
>
|
||||
<span>{{ option.title }}</span>
|
||||
</label>
|
||||
</li>
|
||||
</template>
|
||||
<template v-else>
|
||||
<li class="not-voted" v-for="(option, id) in poll.options" v-bind:key="id">
|
||||
<el-radio v-model="pollRadio" :label="id">{{ option.title }}</el-radio>
|
||||
<li
|
||||
class="not-voted"
|
||||
v-for="(option, id) in poll.options"
|
||||
v-bind:key="id"
|
||||
>
|
||||
<el-radio v-model="pollRadio" :label="id">{{
|
||||
option.title
|
||||
}}</el-radio>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<el-button v-if="!poll.voted" type="success" size="small" @click="vote" :disabled="pollRadio === null">{{
|
||||
$t('cards.toot.poll.vote')
|
||||
<el-button
|
||||
v-if="!poll.voted"
|
||||
type="success"
|
||||
size="small"
|
||||
@click="vote"
|
||||
:disabled="pollRadio === null"
|
||||
>{{ $t('cards.toot.poll.vote') }}</el-button
|
||||
>
|
||||
<el-button v-else type="text" @click="refresh">{{
|
||||
$t('cards.toot.poll.refresh')
|
||||
}}</el-button>
|
||||
<el-button v-else type="text" @click="refresh">{{ $t('cards.toot.poll.refresh') }}</el-button>
|
||||
<span class="votes-count">{{ poll.votes_count }} {{ $t('cards.toot.poll.votes_count') }},</span>
|
||||
<span class="votes-count"
|
||||
>{{ poll.votes_count }} {{ $t('cards.toot.poll.votes_count') }},</span
|
||||
>
|
||||
<span class="until">{{ parseDatetime(poll.expires_at, now) }}</span>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -36,29 +62,33 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
pollRadio: null,
|
||||
now: Date.now()
|
||||
now: Date.now(),
|
||||
}
|
||||
},
|
||||
props: {
|
||||
poll: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language
|
||||
})
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
parseDatetime(datetime, epoch) {
|
||||
switch (this.timeFormat) {
|
||||
case TimeFormat.Absolute.value:
|
||||
return this.$t('cards.toot.poll.until', { datetime: moment(datetime).format('YYYY-MM-DD HH:mm:ss') })
|
||||
return this.$t('cards.toot.poll.until', {
|
||||
datetime: moment(datetime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
})
|
||||
case TimeFormat.Relative.value:
|
||||
moment.locale(this.language)
|
||||
return this.$t('cards.toot.poll.left', { datetime: moment(datetime).from(epoch) })
|
||||
return this.$t('cards.toot.poll.left', {
|
||||
datetime: moment(datetime).from(epoch),
|
||||
})
|
||||
}
|
||||
},
|
||||
percentage(option_votes, poll_votes) {
|
||||
|
@ -77,8 +107,8 @@ export default {
|
|||
},
|
||||
refresh() {
|
||||
this.$emit('refresh', this.poll.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -18,24 +18,24 @@ export default {
|
|||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
accountName: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
body: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
FailoverImg
|
||||
}
|
||||
FailoverImg,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -24,7 +24,12 @@
|
|||
>
|
||||
<font-awesome-icon icon="user-xmark" />
|
||||
</el-button>
|
||||
<el-button v-else-if="relationship.requested" class="requested" type="text" :title="$t('side_bar.account_profile.follow_requested')">
|
||||
<el-button
|
||||
v-else-if="relationship.requested"
|
||||
class="requested"
|
||||
type="text"
|
||||
:title="$t('side_bar.account_profile.follow_requested')"
|
||||
>
|
||||
<font-awesome-icon icon="hourglass" />
|
||||
</el-button>
|
||||
<el-button
|
||||
|
@ -38,10 +43,20 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<div class="tool" v-else-if="request">
|
||||
<el-button class="accept" type="text" @click.stop.prevent="acceptRequest(user)" :title="$t('follow_requests.accept')">
|
||||
<el-button
|
||||
class="accept"
|
||||
type="text"
|
||||
@click.stop.prevent="acceptRequest(user)"
|
||||
:title="$t('follow_requests.accept')"
|
||||
>
|
||||
<font-awesome-icon icon="check" />
|
||||
</el-button>
|
||||
<el-button class="reject" type="text" @click.stop.prevent="rejectRequest(user)" :tilte="$t('follow_requests.reject')">
|
||||
<el-button
|
||||
class="reject"
|
||||
type="text"
|
||||
@click.stop.prevent="rejectRequest(user)"
|
||||
:tilte="$t('follow_requests.reject')"
|
||||
>
|
||||
<font-awesome-icon icon="xmark" />
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -55,25 +70,25 @@ import emojify from '~/src/renderer/utils/emojify'
|
|||
export default {
|
||||
name: 'user',
|
||||
components: {
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
},
|
||||
props: {
|
||||
user: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
remove: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
relationship: {
|
||||
type: Object,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
request: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -84,9 +99,17 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
removeAccount(account) {
|
||||
this.$emit('removeAccount', account)
|
||||
|
@ -102,8 +125,8 @@ export default {
|
|||
},
|
||||
rejectRequest(account) {
|
||||
this.$emit('rejectRequest', account)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -140,29 +140,40 @@ export default {
|
|||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
defalt: false
|
||||
defalt: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Favourite,
|
||||
Follow,
|
||||
FollowRequest,
|
||||
Mention,
|
||||
Quote,
|
||||
Reblog,
|
||||
Reaction,
|
||||
Status,
|
||||
PollVote,
|
||||
PollExpired,
|
||||
},
|
||||
components: { Favourite, Follow, FollowRequest, Mention, Quote, Reblog, Reaction, Status, PollVote, PollExpired },
|
||||
methods: {
|
||||
updateToot(message) {
|
||||
return this.$emit('update', message)
|
||||
},
|
||||
deleteToot(message) {
|
||||
return this.$emit('delete', message)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,25 +32,34 @@
|
|||
v-html="
|
||||
$t('notification.favourite.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" role="presentation" />
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
role="presentation"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
<div class="user" @click="openUser(message.status.account)">
|
||||
<span class="display-name"><bdi v-html="username(message.status.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(message.status.account)"></bdi
|
||||
></span>
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
{{ parseDatetime(message.status.created_at) }}
|
||||
|
@ -59,7 +79,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -72,7 +99,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -81,7 +110,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -89,10 +120,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -126,42 +175,42 @@ export default {
|
|||
name: 'favourite',
|
||||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview
|
||||
LinkPreview,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle,
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -179,7 +228,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -207,17 +256,31 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'favourite')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount.acct
|
||||
}
|
||||
|
@ -230,14 +293,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -252,7 +329,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -284,8 +364,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
<div
|
||||
class="relationship"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? { next: ['j'], prev: ['k'], right: ['l'], profile: ['p'] }
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -20,7 +24,7 @@
|
|||
v-html="
|
||||
$t('notification.follow.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
|
@ -43,26 +47,26 @@ import emojify from '~/src/renderer/utils/emojify'
|
|||
export default {
|
||||
name: 'follow',
|
||||
components: {
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -80,7 +84,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -91,9 +95,17 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
handleStatusControl(event) {
|
||||
switch (event.srcKey) {
|
||||
|
@ -110,8 +122,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
<div
|
||||
class="relationship"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? { next: ['j'], prev: ['k'], right: ['l'], profile: ['p'] }
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -20,7 +24,7 @@
|
|||
v-html="
|
||||
$t('notification.follow_request.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
|
@ -43,26 +47,26 @@ import emojify from '~/src/renderer/utils/emojify'
|
|||
export default {
|
||||
name: 'follow-request',
|
||||
components: {
|
||||
FailoverImg
|
||||
FailoverImg,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -80,7 +84,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -91,9 +95,17 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
handleStatusControl(event) {
|
||||
switch (event.srcKey) {
|
||||
|
@ -110,8 +122,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -24,20 +24,20 @@ export default {
|
|||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: { Toot },
|
||||
methods: {
|
||||
|
@ -46,7 +46,7 @@ export default {
|
|||
},
|
||||
deleteToot(message) {
|
||||
return this.$emit('delete', message)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,25 +32,34 @@
|
|||
v-html="
|
||||
$t('notification.poll_expired.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" role="presentation" />
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
role="presentation"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
<div class="user" @click="openUser(message.status.account)">
|
||||
<span class="display-name"><bdi v-html="username(message.status.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(message.status.account)"></bdi
|
||||
></span>
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
{{ parseDatetime(message.status.created_at) }}
|
||||
|
@ -59,7 +79,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -72,7 +99,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -81,7 +110,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -89,10 +120,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -126,42 +175,42 @@ export default {
|
|||
name: 'poll-expired',
|
||||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview
|
||||
LinkPreview,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle,
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -179,7 +228,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -207,17 +256,31 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'poll-expired')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount.acct
|
||||
}
|
||||
|
@ -230,14 +293,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -252,7 +329,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -284,8 +364,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,25 +32,34 @@
|
|||
v-html="
|
||||
$t('notification.poll_vote.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" role="presentation" />
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
role="presentation"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
<div class="user" @click="openUser(message.status.account)">
|
||||
<span class="display-name"><bdi v-html="username(message.status.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(message.status.account)"></bdi
|
||||
></span>
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
{{ parseDatetime(message.status.created_at) }}
|
||||
|
@ -59,7 +79,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -72,7 +99,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -81,7 +110,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -89,10 +120,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -126,42 +175,42 @@ export default {
|
|||
name: 'poll-vote',
|
||||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview
|
||||
LinkPreview,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle,
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -179,7 +228,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -207,17 +256,31 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'poll-vote')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount.acct
|
||||
}
|
||||
|
@ -230,14 +293,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -252,7 +329,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -284,8 +364,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,20 +32,30 @@
|
|||
v-html="
|
||||
$t('notification.quote.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)" role="presentation">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
|
||||
<div
|
||||
class="icon"
|
||||
@click="openUser(message.status.account)"
|
||||
role="presentation"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
|
@ -50,7 +71,11 @@
|
|||
</div>
|
||||
<div class="content-wrapper">
|
||||
<div class="spoiler" v-show="spoilered(message.status)">
|
||||
<span v-html="emojiText(message.status.spoiler_text, message.status.emojis)"></span>
|
||||
<span
|
||||
v-html="
|
||||
emojiText(message.status.spoiler_text, message.status.emojis)
|
||||
"
|
||||
></span>
|
||||
<el-button
|
||||
v-if="!isShowContent(message.status)"
|
||||
plain
|
||||
|
@ -61,7 +86,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -74,7 +106,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -83,7 +117,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -91,10 +127,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -104,7 +158,12 @@
|
|||
:icon="message.status.reblog.account.avatar"
|
||||
:username="username(message.status.reblog.account)"
|
||||
:accountName="''"
|
||||
:body="emojiText(message.status.reblog.content, message.status.reblog.emojis)"
|
||||
:body="
|
||||
emojiText(
|
||||
message.status.reblog.content,
|
||||
message.status.reblog.emojis
|
||||
)
|
||||
"
|
||||
@select="openDetail(message.status.reblog)"
|
||||
/>
|
||||
<LinkPreview
|
||||
|
@ -138,41 +197,41 @@ export default {
|
|||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview,
|
||||
Quote
|
||||
Quote,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -190,7 +249,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -218,16 +277,30 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'quoted')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(() => {
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount
|
||||
}
|
||||
|
@ -240,14 +313,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -262,7 +349,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -291,8 +381,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,25 +32,34 @@
|
|||
v-html="
|
||||
$t('notification.reaction.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" role="presentation" />
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
role="presentation"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
<div class="user" @click="openUser(message.status.account)">
|
||||
<span class="display-name"><bdi v-html="username(message.status.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(message.status.account)"></bdi
|
||||
></span>
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
{{ parseDatetime(message.status.created_at) }}
|
||||
|
@ -59,7 +79,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -72,7 +99,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -81,7 +110,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -89,10 +120,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -126,42 +175,42 @@ export default {
|
|||
name: 'reaction',
|
||||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview
|
||||
LinkPreview,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle,
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -179,7 +228,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -207,17 +256,31 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'favourite')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount.acct
|
||||
}
|
||||
|
@ -230,14 +293,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -252,7 +329,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -284,8 +364,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,18 @@
|
|||
<div
|
||||
class="status"
|
||||
tabIndex="0"
|
||||
v-shortkey="shortcutEnabled ? { next: ['j'], prev: ['k'], right: ['l'], left: ['h'], open: ['o'], profile: ['p'] } : {}"
|
||||
v-shortkey="
|
||||
shortcutEnabled
|
||||
? {
|
||||
next: ['j'],
|
||||
prev: ['k'],
|
||||
right: ['l'],
|
||||
left: ['h'],
|
||||
open: ['o'],
|
||||
profile: ['p'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
@shortkey="handleStatusControl"
|
||||
ref="status"
|
||||
@click="$emit('select')"
|
||||
|
@ -21,20 +32,30 @@
|
|||
v-html="
|
||||
$t('notification.reblog.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="target" v-on:dblclick="openDetail(message.status)">
|
||||
<div class="icon" @click="openUser(message.status.account)" role="presentation">
|
||||
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
|
||||
<div
|
||||
class="icon"
|
||||
@click="openUser(message.status.account)"
|
||||
role="presentation"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="message.status.account.avatar"
|
||||
:alt="`Avatar of ${message.status.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="toot-header">
|
||||
|
@ -61,7 +82,14 @@
|
|||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else plain type="primary" size="medium" class="spoil-button" @click="showContent = false">
|
||||
<el-button
|
||||
v-else
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="showContent = false"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -74,7 +102,9 @@
|
|||
</div>
|
||||
<div class="attachments">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && !isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && !isShowAttachments(message.status)
|
||||
"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="showAttachments = true"
|
||||
|
@ -83,7 +113,9 @@
|
|||
</el-button>
|
||||
<div v-show="isShowAttachments(message.status)">
|
||||
<el-button
|
||||
v-show="sensitive(message.status) && isShowAttachments(message.status)"
|
||||
v-show="
|
||||
sensitive(message.status) && isShowAttachments(message.status)
|
||||
"
|
||||
class="hide-sensitive"
|
||||
type="text"
|
||||
@click="showAttachments = false"
|
||||
|
@ -91,10 +123,28 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message.status)">
|
||||
<FailoverImg :src="media.preview_url" :title="media.description" :readExif="true" />
|
||||
<el-tag class="media-label" size="mini" v-if="media.type == 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type == 'video'">VIDEO</el-tag>
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments(message.status)"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type == 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type == 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -128,41 +178,41 @@ export default {
|
|||
name: 'reblog',
|
||||
components: {
|
||||
FailoverImg,
|
||||
LinkPreview
|
||||
LinkPreview,
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showContent: false,
|
||||
showAttachments: false
|
||||
showAttachments: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language,
|
||||
hideAllAttachments: state => state.hideAllAttachments
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
hideAllAttachments: (state) => state.hideAllAttachments,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -180,7 +230,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -208,16 +258,30 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'reblog')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', parsedAccount)
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
parsedAccount
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.catch(() => {
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount
|
||||
}
|
||||
|
@ -230,14 +294,28 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
mediaAttachments(message) {
|
||||
return message.media_attachments
|
||||
|
@ -252,7 +330,10 @@ export default {
|
|||
return !this.spoilered(message) || this.showContent
|
||||
},
|
||||
sensitive(message) {
|
||||
return (this.hideAllAttachments || message.sensitive) && this.mediaAttachments(message).length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || message.sensitive) &&
|
||||
this.mediaAttachments(message).length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments(message) {
|
||||
return !this.sensitive(message) || this.showAttachments
|
||||
|
@ -284,8 +365,8 @@ export default {
|
|||
this.openUser(this.message.account)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -10,14 +10,17 @@
|
|||
v-html="
|
||||
$t('notification.status.body', {
|
||||
username: username(message.account),
|
||||
interpolation: { escapeValue: false }
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
"
|
||||
></bdi>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-icon" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -48,20 +51,20 @@ export default {
|
|||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: { Toot, FailoverImg },
|
||||
methods: {
|
||||
|
@ -79,11 +82,19 @@ export default {
|
|||
}
|
||||
},
|
||||
openUser(account) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
}
|
||||
}
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<template>
|
||||
<div class="status-loading" tabIndex="0" @click="onClick">
|
||||
<img v-if="loading" src="../../assets/images/loading-spinner-wide.svg" class="load-icon" />
|
||||
<img
|
||||
v-if="loading"
|
||||
src="../../assets/images/loading-spinner-wide.svg"
|
||||
class="load-icon"
|
||||
/>
|
||||
<p v-else class="load-text">{{ $t('cards.status_loading.message') }}</p>
|
||||
<div class="fill-line"></div>
|
||||
</div>
|
||||
|
@ -12,16 +16,16 @@ export default {
|
|||
props: {
|
||||
max_id: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
since_id: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
|
@ -33,8 +37,8 @@ export default {
|
|||
} else if (this.max_id !== '') {
|
||||
this.$emit('load_max', this.max_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
open: ['o'],
|
||||
profile: ['p'],
|
||||
image: ['i'],
|
||||
cw: ['x']
|
||||
cw: ['x'],
|
||||
}
|
||||
: {}
|
||||
"
|
||||
|
@ -28,8 +28,15 @@
|
|||
<div v-show="filtered" class="filtered">Filtered</div>
|
||||
<div v-show="!filtered" class="toot">
|
||||
<div class="reblogger" v-show="message.reblog && !message.quote">
|
||||
<span class="reblogger-icon" @click="openUser(message.account)" role="presentation">
|
||||
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
|
||||
<span
|
||||
class="reblogger-icon"
|
||||
@click="openUser(message.account)"
|
||||
role="presentation"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="message.account.avatar"
|
||||
:alt="`Avatar of ${message.account.username}`"
|
||||
/>
|
||||
</span>
|
||||
<font-awesome-icon icon="retweet" />
|
||||
<span
|
||||
|
@ -51,11 +58,17 @@
|
|||
<div class="detail" v-on:dblclick="openDetail(message)">
|
||||
<div class="toot-header">
|
||||
<div class="user" @click="openUser(originalMessage.account)">
|
||||
<span class="display-name"><bdi v-html="username(originalMessage.account)"></bdi></span>
|
||||
<span class="display-name"
|
||||
><bdi v-html="username(originalMessage.account)"></bdi
|
||||
></span>
|
||||
<span class="acct">{{ accountName(originalMessage.account) }}</span>
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
<time :datetime="originalMessage.created_at" :title="readableTimestamp" @click="openDetail(message)">
|
||||
<time
|
||||
:datetime="originalMessage.created_at"
|
||||
:title="readableTimestamp"
|
||||
@click="openDetail(message)"
|
||||
>
|
||||
{{ timestamp }}
|
||||
</time>
|
||||
</div>
|
||||
|
@ -63,11 +76,28 @@
|
|||
</div>
|
||||
<div class="content-wrapper">
|
||||
<div class="spoiler" v-show="spoilered">
|
||||
<span v-html="emojiText(originalMessage.spoiler_text, originalMessage.emojis)"></span>
|
||||
<el-button v-if="!isShowContent" plain type="primary" size="medium" class="spoil-button" @click="toggleSpoiler">
|
||||
<span
|
||||
v-html="
|
||||
emojiText(originalMessage.spoiler_text, originalMessage.emojis)
|
||||
"
|
||||
></span>
|
||||
<el-button
|
||||
v-if="!isShowContent"
|
||||
plain
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="toggleSpoiler"
|
||||
>
|
||||
{{ $t('cards.toot.show_more') }}
|
||||
</el-button>
|
||||
<el-button v-else type="primary" size="medium" class="spoil-button" @click="toggleSpoiler">
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="spoil-button"
|
||||
@click="toggleSpoiler"
|
||||
>
|
||||
{{ $t('cards.toot.hide') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -77,10 +107,21 @@
|
|||
v-html="emojiText(originalMessage.content, originalMessage.emojis)"
|
||||
@click.capture.prevent="tootClick"
|
||||
></div>
|
||||
<Poll v-show="isShowContent" v-if="poll" :poll="poll" @vote="vote" @refresh="refresh"></Poll>
|
||||
<Poll
|
||||
v-show="isShowContent"
|
||||
v-if="poll"
|
||||
:poll="poll"
|
||||
@vote="vote"
|
||||
@refresh="refresh"
|
||||
></Poll>
|
||||
</div>
|
||||
<div class="attachments">
|
||||
<el-button v-show="sensitive && !isShowAttachments" class="show-sensitive" type="info" @click="toggleCW()">
|
||||
<el-button
|
||||
v-show="sensitive && !isShowAttachments"
|
||||
class="show-sensitive"
|
||||
type="info"
|
||||
@click="toggleCW()"
|
||||
>
|
||||
{{ $t('cards.toot.sensitive') }}
|
||||
</el-button>
|
||||
<div v-show="isShowAttachments">
|
||||
|
@ -93,16 +134,39 @@
|
|||
>
|
||||
<font-awesome-icon icon="eye" class="hide" />
|
||||
</el-button>
|
||||
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments">
|
||||
<div
|
||||
class="media"
|
||||
v-bind:key="media.preview_url"
|
||||
v-for="media in mediaAttachments"
|
||||
>
|
||||
<FailoverImg
|
||||
:src="media.preview_url ? media.preview_url : originalMessage.account.avatar"
|
||||
:src="
|
||||
media.preview_url
|
||||
? media.preview_url
|
||||
: originalMessage.account.avatar
|
||||
"
|
||||
@click="openImage(media.url, mediaAttachments)"
|
||||
:title="media.description"
|
||||
:readExif="true"
|
||||
/>
|
||||
<el-tag class="media-label" size="mini" v-if="media.type === 'gifv'">GIF</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type === 'video'">VIDEO</el-tag>
|
||||
<el-tag class="media-label" size="mini" v-else-if="media.type === 'audio'">AUDIO</el-tag>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-if="media.type === 'gifv'"
|
||||
>GIF</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type === 'video'"
|
||||
>VIDEO</el-tag
|
||||
>
|
||||
<el-tag
|
||||
class="media-label"
|
||||
size="mini"
|
||||
v-else-if="media.type === 'audio'"
|
||||
>AUDIO</el-tag
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -124,17 +188,33 @@
|
|||
/>
|
||||
<div class="emoji-reactions">
|
||||
<template v-for="reaction in originalMessage.emoji_reactions">
|
||||
<el-button v-if="reaction.me" type="success" size="medium" class="reaction" @click="removeReaction(reaction.name)"
|
||||
<el-button
|
||||
v-if="reaction.me"
|
||||
type="success"
|
||||
size="medium"
|
||||
class="reaction"
|
||||
@click="removeReaction(reaction.name)"
|
||||
>{{ reaction.name }} {{ reaction.count }}</el-button
|
||||
>
|
||||
<el-button v-else type="text" size="medium" class="reaction" @click="addReaction(reaction.name)"
|
||||
<el-button
|
||||
v-else
|
||||
type="text"
|
||||
size="medium"
|
||||
class="reaction"
|
||||
@click="addReaction(reaction.name)"
|
||||
>{{ reaction.name }} {{ reaction.count }}</el-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
<div class="toot-footer">
|
||||
<div class="tool-box">
|
||||
<el-button type="text" @click="openReply()" class="reply" :title="$t('cards.toot.reply')" :aria-label="$t('cards.toot.reply')">
|
||||
<el-button
|
||||
type="text"
|
||||
@click="openReply()"
|
||||
class="reply"
|
||||
:title="$t('cards.toot.reply')"
|
||||
:aria-label="$t('cards.toot.reply')"
|
||||
>
|
||||
<font-awesome-icon icon="reply" size="sm" />
|
||||
</el-button>
|
||||
<el-button v-show="locked" type="text" class="locked">
|
||||
|
@ -158,7 +238,11 @@
|
|||
<el-button
|
||||
type="text"
|
||||
@click="changeFavourite(originalMessage)"
|
||||
:class="originalMessage.favourited ? 'favourited animated bounceIn' : 'favourite'"
|
||||
:class="
|
||||
originalMessage.favourited
|
||||
? 'favourited animated bounceIn'
|
||||
: 'favourite'
|
||||
"
|
||||
:title="$t('cards.toot.fav')"
|
||||
:aria-label="$t('cards.toot.fav')"
|
||||
>
|
||||
|
@ -177,7 +261,12 @@
|
|||
>
|
||||
<font-awesome-icon icon="bookmark" size="sm" />
|
||||
</el-button>
|
||||
<el-button type="text" class="quote-btn" v-if="quoteSupported" @click="openQuote()">
|
||||
<el-button
|
||||
type="text"
|
||||
class="quote-btn"
|
||||
v-if="quoteSupported"
|
||||
@click="openQuote()"
|
||||
>
|
||||
<font-awesome-icon icon="quote-right" size="sm" />
|
||||
</el-button>
|
||||
<template v-if="sns !== 'mastodon'">
|
||||
|
@ -206,7 +295,13 @@
|
|||
</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
<el-button class="pinned" type="text" :title="$t('cards.toot.pinned')" :aria-label="$t('cards.toot.pinned')" v-show="pinned">
|
||||
<el-button
|
||||
class="pinned"
|
||||
type="text"
|
||||
:title="$t('cards.toot.pinned')"
|
||||
:aria-label="$t('cards.toot.pinned')"
|
||||
v-show="pinned"
|
||||
>
|
||||
<font-awesome-icon icon="thumbtack" size="sm" />
|
||||
</el-button>
|
||||
<el-popover
|
||||
|
@ -219,7 +314,11 @@
|
|||
@hide="hideMenu"
|
||||
>
|
||||
<ul class="menu-list" v-if="openToolMenu">
|
||||
<li role="button" @click="openDetail(message)" v-show="!detailed">
|
||||
<li
|
||||
role="button"
|
||||
@click="openDetail(message)"
|
||||
v-show="!detailed"
|
||||
>
|
||||
{{ $t('cards.toot.view_toot_detail') }}
|
||||
</li>
|
||||
<li role="button" @click="openBrowser(originalMessage)">
|
||||
|
@ -237,11 +336,20 @@
|
|||
<li role="button" @click="reportUser()" v-if="!isMyMessage">
|
||||
{{ $t('cards.toot.report') }}
|
||||
</li>
|
||||
<li role="button" class="separate" @click="deleteToot(message)" v-if="isMyMessage">
|
||||
<li
|
||||
role="button"
|
||||
class="separate"
|
||||
@click="deleteToot(message)"
|
||||
v-if="isMyMessage"
|
||||
>
|
||||
{{ $t('cards.toot.delete') }}
|
||||
</li>
|
||||
</ul>
|
||||
<el-button slot="reference" type="text" :title="$t('cards.toot.detail')">
|
||||
<el-button
|
||||
slot="reference"
|
||||
type="text"
|
||||
:title="$t('cards.toot.detail')"
|
||||
>
|
||||
<font-awesome-icon icon="ellipsis" size="sm" />
|
||||
</el-button>
|
||||
</el-popover>
|
||||
|
@ -277,14 +385,14 @@ import Filtered from '@/utils/filter'
|
|||
export default {
|
||||
name: 'toot',
|
||||
directives: {
|
||||
ClickOutside
|
||||
ClickOutside,
|
||||
},
|
||||
components: {
|
||||
FailoverImg,
|
||||
Poll,
|
||||
Picker,
|
||||
LinkPreview,
|
||||
Quote
|
||||
Quote,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -293,47 +401,47 @@ export default {
|
|||
hideAllAttachments: this.$store.state.App.hideAllAttachments,
|
||||
now: Date.now(),
|
||||
openEmojiPicker: false,
|
||||
openToolMenu: false
|
||||
openToolMenu: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
default: {}
|
||||
default: {},
|
||||
},
|
||||
filters: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
overlaid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
pinned: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
detailed: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle,
|
||||
timeFormat: state => state.timeFormat,
|
||||
language: state => state.language
|
||||
displayNameStyle: (state) => state.displayNameStyle,
|
||||
timeFormat: (state) => state.timeFormat,
|
||||
language: (state) => state.language,
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
sns: state => state.sns,
|
||||
account: state => state.account
|
||||
sns: (state) => state.sns,
|
||||
account: (state) => state.account,
|
||||
}),
|
||||
...mapState('TimelineSpace/SideMenu', {
|
||||
bookmarkSupported: state => state.enabledTimelines.bookmark
|
||||
bookmarkSupported: (state) => state.enabledTimelines.bookmark,
|
||||
}),
|
||||
shortcutEnabled: function () {
|
||||
return this.focused && !this.overlaid && !this.openEmojiPicker
|
||||
|
@ -368,7 +476,10 @@ export default {
|
|||
return null
|
||||
},
|
||||
isMyMessage: function () {
|
||||
return this.$store.state.TimelineSpace.account.accountId === this.originalMessage.account.id
|
||||
return (
|
||||
this.$store.state.TimelineSpace.account.accountId ===
|
||||
this.originalMessage.account.id
|
||||
)
|
||||
},
|
||||
application: function () {
|
||||
const msg = this.originalMessage
|
||||
|
@ -387,7 +498,10 @@ export default {
|
|||
return this.originalMessage.poll
|
||||
},
|
||||
sensitive: function () {
|
||||
return (this.hideAllAttachments || this.originalMessage.sensitive) && this.mediaAttachments.length > 0
|
||||
return (
|
||||
(this.hideAllAttachments || this.originalMessage.sensitive) &&
|
||||
this.mediaAttachments.length > 0
|
||||
)
|
||||
},
|
||||
isShowAttachments: function () {
|
||||
return !this.sensitive || this.showAttachments
|
||||
|
@ -403,7 +517,7 @@ export default {
|
|||
},
|
||||
quoteSupported: function () {
|
||||
return QuoteSupported(this.sns, this.account.domain)
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.focused) {
|
||||
|
@ -427,7 +541,7 @@ export default {
|
|||
this.$refs.status.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
username(account) {
|
||||
|
@ -475,20 +589,34 @@ export default {
|
|||
}
|
||||
const parsedAccount = findAccount(e.target, 'toot')
|
||||
if (parsedAccount !== null) {
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/searchAccount', {
|
||||
parsedAccount: parsedAccount,
|
||||
status: this.originalMessage
|
||||
.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/searchAccount',
|
||||
{
|
||||
parsedAccount: parsedAccount,
|
||||
status: this.originalMessage,
|
||||
}
|
||||
)
|
||||
.then((account) => {
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
})
|
||||
.then(account => {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.openLink(e)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', false)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
false
|
||||
)
|
||||
})
|
||||
return parsedAccount.acct
|
||||
}
|
||||
|
@ -501,12 +629,21 @@ export default {
|
|||
}
|
||||
},
|
||||
openReply() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/openReply', this.originalMessage)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/openReply',
|
||||
this.originalMessage
|
||||
)
|
||||
},
|
||||
openDetail(message) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openTootComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/TootDetail/changeToot', message)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/TootDetail/changeToot',
|
||||
message
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
this.$refs.status_menu_popper.doClose()
|
||||
},
|
||||
openBrowser(message) {
|
||||
|
@ -518,11 +655,17 @@ export default {
|
|||
this.$refs.status_menu_popper.doClose()
|
||||
},
|
||||
reportUser() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/Report/openReport', this.originalMessage)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/Report/openReport',
|
||||
this.originalMessage
|
||||
)
|
||||
this.$refs.status_menu_popper.doClose()
|
||||
},
|
||||
confirmMute() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeAccount', this.originalMessage.account)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/MuteConfirm/changeAccount',
|
||||
this.originalMessage.account
|
||||
)
|
||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', true)
|
||||
this.$refs.status_menu_popper.doClose()
|
||||
},
|
||||
|
@ -534,27 +677,27 @@ export default {
|
|||
if (message.reblogged) {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/unreblog', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.unreblog_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/reblog', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.reblog_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -563,27 +706,27 @@ export default {
|
|||
if (message.favourited) {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/removeFavourite', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.unfavourite_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/addFavourite', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.favourite_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -592,57 +735,65 @@ export default {
|
|||
if (message.bookmarked) {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/removeBookmark', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.unbookmark_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/addBookmark', message)
|
||||
.then(data => {
|
||||
.then((data) => {
|
||||
this.$emit('update', data)
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
this.$message({
|
||||
message: this.$t('message.bookmark_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
openImage(url, rawMediaList) {
|
||||
const mediaList = rawMediaList.map(media => {
|
||||
const mediaList = rawMediaList.map((media) => {
|
||||
return media.url
|
||||
})
|
||||
const currentIndex = mediaList.indexOf(url)
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/openModal', {
|
||||
currentIndex: currentIndex,
|
||||
mediaList: rawMediaList
|
||||
mediaList: rawMediaList,
|
||||
})
|
||||
},
|
||||
openUser(account) {
|
||||
console.log(account)
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/changeAccount', account)
|
||||
this.$store.commit('TimelineSpace/Contents/SideBar/changeOpenSideBar', true)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/openAccountComponent'
|
||||
)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Contents/SideBar/AccountProfile/changeAccount',
|
||||
account
|
||||
)
|
||||
this.$store.commit(
|
||||
'TimelineSpace/Contents/SideBar/changeOpenSideBar',
|
||||
true
|
||||
)
|
||||
},
|
||||
deleteToot(message) {
|
||||
this.$store
|
||||
.dispatch('organisms/Toot/deleteToot', message)
|
||||
.then(message => {
|
||||
.then((message) => {
|
||||
this.$emit('delete', message)
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.delete_error'),
|
||||
type: 'error'
|
||||
type: 'error',
|
||||
})
|
||||
})
|
||||
},
|
||||
|
@ -695,24 +846,24 @@ export default {
|
|||
async vote(choices) {
|
||||
const res = await this.$store.dispatch('organisms/Toot/vote', {
|
||||
id: this.poll.id,
|
||||
choices: choices
|
||||
choices: choices,
|
||||
})
|
||||
const status = Object.assign({}, this.originalMessage, {
|
||||
poll: res
|
||||
poll: res,
|
||||
})
|
||||
this.$emit('update', status)
|
||||
},
|
||||
async refresh(id) {
|
||||
const res = await this.$store.dispatch('organisms/Toot/refresh', id)
|
||||
const status = Object.assign({}, this.originalMessage, {
|
||||
poll: res
|
||||
poll: res,
|
||||
})
|
||||
this.$emit('update', status)
|
||||
},
|
||||
async selectEmoji(emoji) {
|
||||
const status = await this.$store.dispatch('organisms/Toot/sendReaction', {
|
||||
status_id: this.originalMessage.id,
|
||||
native: emoji.native
|
||||
native: emoji.native,
|
||||
})
|
||||
this.$emit('update', status)
|
||||
this.$refs.status_emoji_picker.doClose()
|
||||
|
@ -720,19 +871,25 @@ export default {
|
|||
async addReaction(native) {
|
||||
const status = await this.$store.dispatch('organisms/Toot/sendReaction', {
|
||||
status_id: this.originalMessage.id,
|
||||
native: native
|
||||
native: native,
|
||||
})
|
||||
this.$emit('update', status)
|
||||
},
|
||||
async removeReaction(native) {
|
||||
const status = await this.$store.dispatch('organisms/Toot/deleteReaction', {
|
||||
status_id: this.originalMessage.id,
|
||||
native: native
|
||||
})
|
||||
const status = await this.$store.dispatch(
|
||||
'organisms/Toot/deleteReaction',
|
||||
{
|
||||
status_id: this.originalMessage.id,
|
||||
native: native,
|
||||
}
|
||||
)
|
||||
this.$emit('update', status)
|
||||
},
|
||||
openQuote() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/openQuote', this.originalMessage)
|
||||
this.$store.dispatch(
|
||||
'TimelineSpace/Modals/NewToot/openQuote',
|
||||
this.originalMessage
|
||||
)
|
||||
},
|
||||
openPicker() {
|
||||
this.openEmojiPicker = true
|
||||
|
@ -753,8 +910,8 @@ export default {
|
|||
toggleCW() {
|
||||
this.showAttachments = !this.showAttachments
|
||||
this.$emit('sizeChanged', true)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import loadImage from 'blueimp-load-image'
|
||||
|
||||
const parseExtension = url => {
|
||||
const parseExtension = (url) => {
|
||||
if (!url) {
|
||||
return null
|
||||
}
|
||||
if (url.match(/\.jpg$/) || url.match(/\.jpeg$/) || url.match(/\.JPG$/) || url.match(/\.JPEG$/)) {
|
||||
if (
|
||||
url.match(/\.jpg$/) ||
|
||||
url.match(/\.jpeg$/) ||
|
||||
url.match(/\.JPG$/) ||
|
||||
url.match(/\.JPEG$/)
|
||||
) {
|
||||
return 'image/jpeg'
|
||||
} else if (url.match(/\.png$/) || url.match(/\.PNG$/)) {
|
||||
return 'image/png'
|
||||
|
@ -18,7 +23,7 @@ const parseExtension = url => {
|
|||
return null
|
||||
}
|
||||
|
||||
const exifImageUrl = url => {
|
||||
const exifImageUrl = (url) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const extension = parseExtension(url)
|
||||
if (!extension) {
|
||||
|
@ -26,7 +31,7 @@ const exifImageUrl = url => {
|
|||
}
|
||||
loadImage(
|
||||
url,
|
||||
canvas => {
|
||||
(canvas) => {
|
||||
if (canvas.type === 'error') {
|
||||
return reject(Error(`can not load image: ${url}`))
|
||||
}
|
||||
|
@ -36,7 +41,7 @@ const exifImageUrl = url => {
|
|||
{
|
||||
canvas: true,
|
||||
meta: true,
|
||||
orientation: true
|
||||
orientation: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
|
|
@ -46,10 +46,12 @@ export class ScrollPosition {
|
|||
}
|
||||
|
||||
prepare() {
|
||||
this.previousScrollHeightMinusTop = this.node.scrollHeight - this.node.scrollTop
|
||||
this.previousScrollHeightMinusTop =
|
||||
this.node.scrollHeight - this.node.scrollTop
|
||||
}
|
||||
|
||||
restore() {
|
||||
this.node.scrollTop = this.node.scrollHeight - this.previousScrollHeightMinusTop
|
||||
this.node.scrollTop =
|
||||
this.node.scrollHeight - this.previousScrollHeightMinusTop
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue