eslint --fix --ext .js,.vue src

This commit is contained in:
Henry Jameson 2019-07-05 10:17:44 +03:00
parent 2c2b84d31d
commit 8d6750d9c2
86 changed files with 4963 additions and 2283 deletions

View file

@ -1,53 +1,111 @@
<template> <template>
<div id="app" v-bind:style="bgAppStyle"> <div
<div class="app-bg-wrapper" v-bind:style="bgStyle"></div> id="app"
:style="bgAppStyle"
>
<div
class="app-bg-wrapper"
:style="bgStyle"
/>
<MobileNav v-if="isMobileLayout" /> <MobileNav v-if="isMobileLayout" />
<nav v-else class='nav-bar container' @click="scrollToTop()" id="nav"> <nav
<div class='logo' :style='logoBgStyle'> v-else
<div class='mask' :style='logoMaskStyle'></div> id="nav"
<img :src='logo' :style='logoStyle'> class="nav-bar container"
@click="scrollToTop()"
>
<div
class="logo"
:style="logoBgStyle"
>
<div
class="mask"
:style="logoMaskStyle"
/>
<img
:src="logo"
:style="logoStyle"
>
</div> </div>
<div class='inner-nav'> <div class="inner-nav">
<div class='item'> <div class="item">
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link> <router-link
class="site-name"
:to="{ name: 'root' }"
active-class="home"
>
{{ sitename }}
</router-link>
</div> </div>
<div class='item right'> <div class="item right">
<user-finder class="button-icon nav-icon mobile-hidden" @toggled="onFinderToggled"></user-finder> <user-finder
<router-link class="mobile-hidden" :to="{ name: 'settings'}"><i class="button-icon icon-cog nav-icon" :title="$t('nav.preferences')"></i></router-link> class="button-icon nav-icon mobile-hidden"
<a href="#" class="mobile-hidden" v-if="currentUser" @click.prevent="logout"><i class="button-icon icon-logout nav-icon" :title="$t('login.logout')"></i></a> @toggled="onFinderToggled"
/>
<router-link
class="mobile-hidden"
:to="{ name: 'settings'}"
>
<i
class="button-icon icon-cog nav-icon"
:title="$t('nav.preferences')"
/>
</router-link>
<a
v-if="currentUser"
href="#"
class="mobile-hidden"
@click.prevent="logout"
><i
class="button-icon icon-logout nav-icon"
:title="$t('login.logout')"
/></a>
</div> </div>
</div> </div>
</nav> </nav>
<div class="container" id="content"> <div
id="content"
class="container"
>
<div class="sidebar-flexer mobile-hidden"> <div class="sidebar-flexer mobile-hidden">
<div class="sidebar-bounds"> <div class="sidebar-bounds">
<div class="sidebar-scroller"> <div class="sidebar-scroller">
<div class="sidebar"> <div class="sidebar">
<user-panel></user-panel> <user-panel />
<div v-if="!isMobileLayout"> <div v-if="!isMobileLayout">
<nav-panel></nav-panel> <nav-panel />
<instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel> <instance-specific-panel v-if="showInstanceSpecificPanel" />
<features-panel v-if="!currentUser && showFeaturesPanel"></features-panel> <features-panel v-if="!currentUser && showFeaturesPanel" />
<who-to-follow-panel v-if="currentUser && suggestionsEnabled"></who-to-follow-panel> <who-to-follow-panel v-if="currentUser && suggestionsEnabled" />
<notifications v-if="currentUser"></notifications> <notifications v-if="currentUser" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="main"> <div class="main">
<div v-if="!currentUser" class="login-hint panel panel-default"> <div
<router-link :to="{ name: 'login' }" class="panel-body"> v-if="!currentUser"
class="login-hint panel panel-default"
>
<router-link
:to="{ name: 'login' }"
class="panel-body"
>
{{ $t("login.hint") }} {{ $t("login.hint") }}
</router-link> </router-link>
</div> </div>
<transition name="fade"> <transition name="fade">
<router-view></router-view> <router-view />
</transition> </transition>
</div> </div>
<media-modal></media-modal> <media-modal />
</div> </div>
<chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel> <chat-panel
v-if="currentUser && chat"
:floating="true"
class="floating-chat mobile-hidden"
/>
<UserReportingModal /> <UserReportingModal />
<portal-target name="modal" /> <portal-target name="modal" />
</div> </div>

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="sidebar"> <div class="sidebar">
<instance-specific-panel></instance-specific-panel> <instance-specific-panel />
<features-panel v-if="showFeaturesPanel"></features-panel> <features-panel v-if="showFeaturesPanel" />
<terms-of-service-panel></terms-of-service-panel> <terms-of-service-panel />
</div> </div>
</template> </template>

View file

@ -1,54 +1,104 @@
<template> <template>
<div v-if="usePlaceHolder" @click="openModal"> <div
<a class="placeholder" v-if="usePlaceHolder"
@click="openModal"
>
<a
v-if="type !== 'html'" v-if="type !== 'html'"
target="_blank" :href="attachment.url" class="placeholder"
target="_blank"
:href="attachment.url"
> >
[{{nsfw ? "NSFW/" : ""}}{{type.toUpperCase()}}] [{{ nsfw ? "NSFW/" : "" }}{{ type.toUpperCase() }}]
</a> </a>
</div> </div>
<div <div
v-else class="attachment" v-else
:class="{[type]: true, loading, 'fullwidth': fullwidth, 'nsfw-placeholder': hidden}"
v-show="!isEmpty" v-show="!isEmpty"
class="attachment"
:class="{[type]: true, loading, 'fullwidth': fullwidth, 'nsfw-placeholder': hidden}"
> >
<a class="image-attachment" v-if="hidden" :href="attachment.url" @click.prevent="toggleHidden"> <a
<img class="nsfw" :key="nsfwImage" :src="nsfwImage" :class="{'small': isSmall}"/> v-if="hidden"
<i v-if="type === 'video'" class="play-icon icon-play-circled"></i> class="image-attachment"
:href="attachment.url"
@click.prevent="toggleHidden"
>
<img
:key="nsfwImage"
class="nsfw"
:src="nsfwImage"
:class="{'small': isSmall}"
>
<i
v-if="type === 'video'"
class="play-icon icon-play-circled"
/>
</a> </a>
<div class="hider" v-if="nsfw && hideNsfwLocal && !hidden"> <div
<a href="#" @click.prevent="toggleHidden">Hide</a> v-if="nsfw && hideNsfwLocal && !hidden"
class="hider"
>
<a
href="#"
@click.prevent="toggleHidden"
>Hide</a>
</div> </div>
<a v-if="type === 'image' && (!hidden || preloadImage)" <a
@click="openModal" v-if="type === 'image' && (!hidden || preloadImage)"
class="image-attachment" class="image-attachment"
:class="{'hidden': hidden && preloadImage }" :class="{'hidden': hidden && preloadImage }"
:href="attachment.url" target="_blank" :href="attachment.url"
target="_blank"
:title="attachment.description" :title="attachment.description"
@click="openModal"
> >
<StillImage :referrerpolicy="referrerpolicy" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/> <StillImage
:referrerpolicy="referrerpolicy"
:mimetype="attachment.mimetype"
:src="attachment.large_thumb_url || attachment.url"
/>
</a> </a>
<a class="video-container" <a
@click="openModal"
v-if="type === 'video' && !hidden" v-if="type === 'video' && !hidden"
class="video-container"
:class="{'small': isSmall}" :class="{'small': isSmall}"
:href="allowPlay ? undefined : attachment.url" :href="allowPlay ? undefined : attachment.url"
@click="openModal"
> >
<VideoAttachment class="video" :attachment="attachment" :controls="allowPlay" /> <VideoAttachment
<i v-if="!allowPlay" class="play-icon icon-play-circled"></i> class="video"
:attachment="attachment"
:controls="allowPlay"
/>
<i
v-if="!allowPlay"
class="play-icon icon-play-circled"
/>
</a> </a>
<audio v-if="type === 'audio'" :src="attachment.url" controls></audio> <audio
v-if="type === 'audio'"
:src="attachment.url"
controls
/>
<div @click.prevent="linkClicked" v-if="type === 'html' && attachment.oembed" class="oembed"> <div
<div v-if="attachment.thumb_url" class="image"> v-if="type === 'html' && attachment.oembed"
<img :src="attachment.thumb_url"/> class="oembed"
@click.prevent="linkClicked"
>
<div
v-if="attachment.thumb_url"
class="image"
>
<img :src="attachment.thumb_url">
</div> </div>
<div class="text"> <div class="text">
<h1><a :href="attachment.url">{{attachment.oembed.title}}</a></h1> <h1><a :href="attachment.url">{{ attachment.oembed.title }}</a></h1>
<div v-html="attachment.oembed.oembedHTML"></div> <div v-html="attachment.oembed.oembedHTML" />
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,8 +1,22 @@
<template> <template>
<div class="autosuggest" v-click-outside="onClickOutside"> <div
<input v-model="term" :placeholder="placeholder" @click="onInputClick" class="autosuggest-input" /> v-click-outside="onClickOutside"
<div class="autosuggest-results" v-if="resultsVisible && filtered.length > 0"> class="autosuggest"
<slot v-for="item in filtered" :item="item" /> >
<input
v-model="term"
:placeholder="placeholder"
class="autosuggest-input"
@click="onInputClick"
>
<div
v-if="resultsVisible && filtered.length > 0"
class="autosuggest-results"
>
<slot
v-for="item in filtered"
:item="item"
/>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,12 +1,15 @@
<template> <template>
<div class="avatars"> <div class="avatars">
<router-link <router-link
:to="userProfileLink(user)"
class="avatars-item"
v-for="user in slicedUsers" v-for="user in slicedUsers"
:key="user.id" :key="user.id"
:to="userProfileLink(user)"
class="avatars-item"
> >
<UserAvatar :user="user" class="avatar-small" /> <UserAvatar
:user="user"
class="avatar-small"
/>
</router-link> </router-link>
</div> </div>
</template> </template>

View file

@ -7,20 +7,43 @@
@click.prevent.native="toggleUserExpanded" @click.prevent.native="toggleUserExpanded"
/> />
</router-link> </router-link>
<div class="basic-user-card-expanded-content" v-if="userExpanded"> <div
<UserCard :user="user" :rounded="true" :bordered="true"/> v-if="userExpanded"
class="basic-user-card-expanded-content"
>
<UserCard
:user="user"
:rounded="true"
:bordered="true"
/>
</div> </div>
<div class="basic-user-card-collapsed-content" v-else> <div
<div :title="user.name" class="basic-user-card-user-name"> v-else
<span v-if="user.name_html" class="basic-user-card-user-name-value" v-html="user.name_html"></span> class="basic-user-card-collapsed-content"
<span v-else class="basic-user-card-user-name-value">{{ user.name }}</span> >
<div
:title="user.name"
class="basic-user-card-user-name"
>
<span
v-if="user.name_html"
class="basic-user-card-user-name-value"
v-html="user.name_html"
/>
<span
v-else
class="basic-user-card-user-name-value"
>{{ user.name }}</span>
</div> </div>
<div> <div>
<router-link class="basic-user-card-screen-name" :to="userProfileLink(user)"> <router-link
@{{user.screen_name}} class="basic-user-card-screen-name"
:to="userProfileLink(user)"
>
@{{ user.screen_name }}
</router-link> </router-link>
</div> </div>
<slot></slot> <slot />
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,7 +1,12 @@
<template> <template>
<basic-user-card :user="user"> <basic-user-card :user="user">
<div class="block-card-content-container"> <div class="block-card-content-container">
<button class="btn btn-default" @click="unblockUser" :disabled="progress" v-if="blocked"> <button
v-if="blocked"
class="btn btn-default"
:disabled="progress"
@click="unblockUser"
>
<template v-if="progress"> <template v-if="progress">
{{ $t('user_card.unblock_progress') }} {{ $t('user_card.unblock_progress') }}
</template> </template>
@ -9,7 +14,12 @@
{{ $t('user_card.unblock') }} {{ $t('user_card.unblock') }}
</template> </template>
</button> </button>
<button class="btn btn-default" @click="blockUser" :disabled="progress" v-else> <button
v-else
class="btn btn-default"
:disabled="progress"
@click="blockUser"
>
<template v-if="progress"> <template v-if="progress">
{{ $t('user_card.block_progress') }} {{ $t('user_card.block_progress') }}
</template> </template>

View file

@ -1,41 +1,70 @@
<template> <template>
<div class="chat-panel" v-if="!this.collapsed || !this.floating"> <div
v-if="!this.collapsed || !this.floating"
class="chat-panel"
>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading timeline-heading" :class="{ 'chat-heading': floating }" @click.stop.prevent="togglePanel"> <div
class="panel-heading timeline-heading"
:class="{ 'chat-heading': floating }"
@click.stop.prevent="togglePanel"
>
<div class="title"> <div class="title">
<span>{{$t('chat.title')}}</span> <span>{{ $t('chat.title') }}</span>
<i class="icon-cancel" v-if="floating"></i> <i
v-if="floating"
class="icon-cancel"
/>
</div> </div>
</div> </div>
<div class="chat-window" v-chat-scroll> <div
<div class="chat-message" v-for="message in messages" :key="message.id"> v-chat-scroll
class="chat-window"
>
<div
v-for="message in messages"
:key="message.id"
class="chat-message"
>
<span class="chat-avatar"> <span class="chat-avatar">
<img :src="message.author.avatar" /> <img :src="message.author.avatar">
</span> </span>
<div class="chat-content"> <div class="chat-content">
<router-link <router-link
class="chat-name" class="chat-name"
:to="userProfileLink(message.author)"> :to="userProfileLink(message.author)"
{{message.author.username}} >
{{ message.author.username }}
</router-link> </router-link>
<br> <br>
<span class="chat-text"> <span class="chat-text">
{{message.text}} {{ message.text }}
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<div class="chat-input"> <div class="chat-input">
<textarea @keyup.enter="submit(currentMessage)" v-model="currentMessage" class="chat-input-textarea" rows="1"></textarea> <textarea
v-model="currentMessage"
class="chat-input-textarea"
rows="1"
@keyup.enter="submit(currentMessage)"
/>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="chat-panel"> <div
v-else
class="chat-panel"
>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading stub timeline-heading chat-heading" @click.stop.prevent="togglePanel"> <div
class="panel-heading stub timeline-heading chat-heading"
@click.stop.prevent="togglePanel"
>
<div class="title"> <div class="title">
<i class="icon-comment-empty"></i> <i class="icon-comment-empty" />
{{$t('chat.title')}} {{ $t('chat.title') }}
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,8 +1,13 @@
<template> <template>
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" :indeterminate.prop="indeterminate"> <input
type="checkbox"
:checked="checked"
:indeterminate.prop="indeterminate"
@change="$emit('change', $event.target.checked)"
>
<i class="checkbox-indicator" /> <i class="checkbox-indicator" />
<span v-if="!!$slots.default"><slot></slot></span> <span v-if="!!$slots.default"><slot /></span>
</label> </label>
</template> </template>

View file

@ -1,33 +1,44 @@
<template> <template>
<div class="color-control style-control" :class="{ disabled: !present || disabled }"> <div
<label :for="name" class="label"> class="color-control style-control"
{{label}} :class="{ disabled: !present || disabled }"
</label> >
<input <label
v-if="typeof fallback !== 'undefined'" :for="name"
class="opt exlcude-disabled" class="label"
:id="name + '-o'"
type="checkbox"
:checked="present"
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)">
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
<input
:id="name"
class="color-input"
type="color"
:value="value || fallback"
:disabled="!present || disabled"
@input="$emit('input', $event.target.value)"
> >
<input {{ label }}
:id="name + '-t'" </label>
class="text-input" <input
type="text" v-if="typeof fallback !== 'undefined'"
:value="value || fallback" :id="name + '-o'"
:disabled="!present || disabled" class="opt exlcude-disabled"
@input="$emit('input', $event.target.value)" type="checkbox"
:checked="present"
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)"
> >
</div> <label
v-if="typeof fallback !== 'undefined'"
class="opt-l"
:for="name + '-o'"
/>
<input
:id="name"
class="color-input"
type="color"
:value="value || fallback"
:disabled="!present || disabled"
@input="$emit('input', $event.target.value)"
>
<input
:id="name + '-t'"
class="text-input"
type="text"
:value="value || fallback"
:disabled="!present || disabled"
@input="$emit('input', $event.target.value)"
>
</div>
</template> </template>
<script> <script>

View file

@ -1,28 +1,38 @@
<template> <template>
<span v-if="contrast" class="contrast-ratio"> <span
<span :title="hint" class="rating"> v-if="contrast"
<span v-if="contrast.aaa"> class="contrast-ratio"
<i class="icon-thumbs-up-alt"/> >
<span
:title="hint"
class="rating"
>
<span v-if="contrast.aaa">
<i class="icon-thumbs-up-alt" />
</span>
<span v-if="!contrast.aaa && contrast.aa">
<i class="icon-adjust" />
</span>
<span v-if="!contrast.aaa && !contrast.aa">
<i class="icon-attention" />
</span>
</span> </span>
<span v-if="!contrast.aaa && contrast.aa"> <span
<i class="icon-adjust"/> v-if="contrast && large"
</span> class="rating"
<span v-if="!contrast.aaa && !contrast.aa"> :title="hint_18pt"
<i class="icon-attention"/> >
<span v-if="contrast.laaa">
<i class="icon-thumbs-up-alt" />
</span>
<span v-if="!contrast.laaa && contrast.laa">
<i class="icon-adjust" />
</span>
<span v-if="!contrast.laaa && !contrast.laa">
<i class="icon-attention" />
</span>
</span> </span>
</span> </span>
<span class="rating" v-if="contrast && large" :title="hint_18pt">
<span v-if="contrast.laaa">
<i class="icon-thumbs-up-alt"/>
</span>
<span v-if="!contrast.laaa && contrast.laa">
<i class="icon-adjust"/>
</span>
<span v-if="!contrast.laaa && !contrast.laa">
<i class="icon-attention"/>
</span>
</span>
</span>
</template> </template>
<script> <script>

View file

@ -1,9 +1,9 @@
<template> <template>
<conversation <conversation
:collapsable="false" :collapsable="false"
isPage="true" is-page="true"
:statusoid="statusoid" :statusoid="statusoid"
></conversation> />
</template> </template>
<script src="./conversation-page.js"></script> <script src="./conversation-page.js"></script>

View file

@ -1,25 +1,34 @@
<template> <template>
<div class="timeline panel-default" :class="[isExpanded ? 'panel' : 'panel-disabled']"> <div
<div v-if="isExpanded" class="panel-heading conversation-heading"> class="timeline panel-default"
:class="[isExpanded ? 'panel' : 'panel-disabled']"
>
<div
v-if="isExpanded"
class="panel-heading conversation-heading"
>
<span class="title"> {{ $t('timeline.conversation') }} </span> <span class="title"> {{ $t('timeline.conversation') }} </span>
<span v-if="collapsable"> <span v-if="collapsable">
<a href="#" @click.prevent="toggleExpanded">{{ $t('timeline.collapse') }}</a> <a
href="#"
@click.prevent="toggleExpanded"
>{{ $t('timeline.collapse') }}</a>
</span> </span>
</div> </div>
<status <status
v-for="status in conversation" v-for="status in conversation"
@goto="setHighlight"
@toggleExpanded="toggleExpanded"
:key="status.id" :key="status.id"
:inlineExpanded="collapsable && isExpanded" :inline-expanded="collapsable && isExpanded"
:statusoid="status" :statusoid="status"
:expandable='!isExpanded' :expandable="!isExpanded"
:showPinned="showPinned" :show-pinned="showPinned"
:focused="focused(status.id)" :focused="focused(status.id)"
:inConversation="isExpanded" :in-conversation="isExpanded"
:highlight="getHighlight()" :highlight="getHighlight()"
:replies="getReplies(status.id)" :replies="getReplies(status.id)"
@goto="setHighlight"
class="status-fadein panel-body" class="status-fadein panel-body"
@toggleExpanded="toggleExpanded"
/> />
</div> </div>
</template> </template>

View file

@ -1,16 +1,22 @@
<template> <template>
<span v-bind:class="{ 'dark-overlay': darkOverlay }" @click.self.stop='onCancel()'> <span
<div class="dialog-modal panel panel-default" @click.stop=''> :class="{ 'dark-overlay': darkOverlay }"
@click.self.stop="onCancel()"
>
<div
class="dialog-modal panel panel-default"
@click.stop=""
>
<div class="panel-heading dialog-modal-heading"> <div class="panel-heading dialog-modal-heading">
<div class="title"> <div class="title">
<slot name="header"></slot> <slot name="header" />
</div> </div>
</div> </div>
<div class="dialog-modal-content"> <div class="dialog-modal-content">
<slot name="default"></slot> <slot name="default" />
</div> </div>
<div class="dialog-modal-footer user-interactions panel-footer"> <div class="dialog-modal-footer user-interactions panel-footer">
<slot name="footer"></slot> <slot name="footer" />
</div> </div>
</div> </div>
</span> </span>

View file

@ -1,5 +1,9 @@
<template> <template>
<Timeline :title="$t('nav.dms')" v-bind:timeline="timeline" v-bind:timeline-name="'dms'"/> <Timeline
:title="$t('nav.dms')"
:timeline="timeline"
:timeline-name="'dms'"
/>
</template> </template>
<script src="./dm_timeline.js"></script> <script src="./dm_timeline.js"></script>

View file

@ -1,27 +1,34 @@
<template> <template>
<div class="emoji-input"> <div class="emoji-input">
<slot></slot> <slot />
<div ref="panel" class="autocomplete-panel" :class="{ hide: !showPopup }"> <div
<div class="autocomplete-panel-body"> ref="panel"
<div class="autocomplete-panel"
v-for="(suggestion, index) in suggestions" :class="{ hide: !showPopup }"
:key="index" >
@click.stop.prevent="onClick($event, suggestion)" <div class="autocomplete-panel-body">
class="autocomplete-item" <div
:class="{ highlighted: suggestion.highlighted }" v-for="(suggestion, index) in suggestions"
:key="index"
class="autocomplete-item"
:class="{ highlighted: suggestion.highlighted }"
@click.stop.prevent="onClick($event, suggestion)"
> >
<span class="image"> <span class="image">
<img v-if="suggestion.img":src="suggestion.img" /> <img
<span v-else>{{suggestion.replacement}}</span> v-if="suggestion.img"
</span> :src="suggestion.img"
<div class="label"> >
<span class="displayText">{{suggestion.displayText}}</span> <span v-else>{{ suggestion.replacement }}</span>
<span class="detailText">{{suggestion.detailText}}</span> </span>
<div class="label">
<span class="displayText">{{ suggestion.displayText }}</span>
<span class="detailText">{{ suggestion.detailText }}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script src="./emoji-input.js"></script> <script src="./emoji-input.js"></script>
@ -103,7 +110,6 @@
} }
} }
input, textarea { input, textarea {
flex: 1 0 auto; flex: 1 0 auto;
} }

View file

@ -1,12 +1,27 @@
<template> <template>
<div class="import-export-container"> <div class="import-export-container">
<slot name="before"/> <slot name="before" />
<button class="btn" @click="exportData">{{ exportLabel }}</button> <button
<button class="btn" @click="importData">{{ importLabel }}</button> class="btn"
<slot name="afterButtons"/> @click="exportData"
<p v-if="importFailed" class="alert error">{{ importFailedText }}</p> >
<slot name="afterError"/> {{ exportLabel }}
</div> </button>
<button
class="btn"
@click="importData"
>
{{ importLabel }}
</button>
<slot name="afterButtons" />
<p
v-if="importFailed"
class="alert error"
>
{{ importFailedText }}
</p>
<slot name="afterError" />
</div>
</template> </template>
<script> <script>
@ -49,7 +64,7 @@ export default {
if (event.target.files[0]) { if (event.target.files[0]) {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const reader = new FileReader() const reader = new FileReader()
reader.onload = ({target}) => { reader.onload = ({ target }) => {
try { try {
const parsed = JSON.parse(target.result) const parsed = JSON.parse(target.result)
const valid = this.validator(parsed) const valid = this.validator(parsed)

View file

@ -1,10 +1,16 @@
<template> <template>
<div class="exporter"> <div class="exporter">
<div v-if="processing"> <div v-if="processing">
<i class="icon-spin4 animate-spin exporter-processing"></i> <i class="icon-spin4 animate-spin exporter-processing" />
<span>{{processingMessage}}</span> <span>{{ processingMessage }}</span>
</div> </div>
<button class="btn btn-default" @click="process" v-else>{{exportButtonLabel}}</button> <button
v-else
class="btn btn-default"
@click="process"
>
{{ exportButtonLabel }}
</button>
</div> </div>
</template> </template>

View file

@ -1,9 +1,8 @@
<template> <template>
<Popper <Popper
trigger="click"
@hide='showDropDown = false'
append-to-body
v-if="enabled && showPopper" v-if="enabled && showPopper"
trigger="click"
append-to-body
:options="{ :options="{
placement: 'top', placement: 'top',
modifiers: { modifiers: {
@ -11,22 +10,42 @@
offset: { offset: '0, 5px' }, offset: { offset: '0, 5px' },
} }
}" }"
@hide="showDropDown = false"
> >
<div class="popper-wrapper"> <div class="popper-wrapper">
<div class="dropdown-menu"> <div class="dropdown-menu">
<button class="dropdown-item dropdown-item-icon" @click.prevent="pinStatus" v-if="!status.pinned && canPin"> <button
<i class="icon-pin"></i><span>{{$t("status.pin")}}</span> v-if="!status.pinned && canPin"
class="dropdown-item dropdown-item-icon"
@click.prevent="pinStatus"
>
<i class="icon-pin" /><span>{{ $t("status.pin") }}</span>
</button> </button>
<button class="dropdown-item dropdown-item-icon" @click.prevent="unpinStatus" v-if="status.pinned && canPin"> <button
<i class="icon-pin"></i><span>{{$t("status.unpin")}}</span> v-if="status.pinned && canPin"
class="dropdown-item dropdown-item-icon"
@click.prevent="unpinStatus"
>
<i class="icon-pin" /><span>{{ $t("status.unpin") }}</span>
</button> </button>
<button class="dropdown-item dropdown-item-icon" @click.prevent="deleteStatus" v-if="canDelete"> <button
<i class="icon-cancel"></i><span>{{$t("status.delete")}}</span> v-if="canDelete"
class="dropdown-item dropdown-item-icon"
@click.prevent="deleteStatus"
>
<i class="icon-cancel" /><span>{{ $t("status.delete") }}</span>
</button> </button>
</div> </div>
</div> </div>
<div class="button-icon" slot="reference" @click="toggleMenu"> <div
<i class='icon-ellipsis' :class="{'icon-clicked': showDropDown}"></i> slot="reference"
class="button-icon"
@click="toggleMenu"
>
<i
class="icon-ellipsis"
:class="{'icon-clicked': showDropDown}"
/>
</div> </div>
</Popper> </Popper>
</template> </template>

View file

@ -1,11 +1,20 @@
<template> <template>
<div v-if="loggedIn"> <div v-if="loggedIn">
<i :class='classes' class='button-icon favorite-button fav-active' @click.prevent='favorite()' :title="$t('tool_tip.favorite')"/> <i
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span> :class="classes"
class="button-icon favorite-button fav-active"
:title="$t('tool_tip.favorite')"
@click.prevent="favorite()"
/>
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
</div> </div>
<div v-else> <div v-else>
<i :class='classes' class='button-icon favorite-button' :title="$t('tool_tip.favorite')"/> <i
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span> :class="classes"
class="button-icon favorite-button"
:title="$t('tool_tip.favorite')"
/>
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
</div> </div>
</template> </template>

View file

@ -3,17 +3,25 @@
<div class="panel panel-default base01-background"> <div class="panel panel-default base01-background">
<div class="panel-heading timeline-heading base02-background base04"> <div class="panel-heading timeline-heading base02-background base04">
<div class="title"> <div class="title">
{{$t('features_panel.title')}} {{ $t('features_panel.title') }}
</div> </div>
</div> </div>
<div class="panel-body features-panel"> <div class="panel-body features-panel">
<ul> <ul>
<li v-if="chat">{{$t('features_panel.chat')}}</li> <li v-if="chat">
<li v-if="gopher">{{$t('features_panel.gopher')}}</li> {{ $t('features_panel.chat') }}
<li v-if="whoToFollow">{{$t('features_panel.who_to_follow')}}</li> </li>
<li v-if="mediaProxy">{{$t('features_panel.media_proxy')}}</li> <li v-if="gopher">
<li>{{$t('features_panel.scope_options')}}</li> {{ $t('features_panel.gopher') }}
<li>{{$t('features_panel.text_limit')}} = {{textlimit}}</li> </li>
<li v-if="whoToFollow">
{{ $t('features_panel.who_to_follow') }}
</li>
<li v-if="mediaProxy">
{{ $t('features_panel.media_proxy') }}
</li>
<li>{{ $t('features_panel.scope_options') }}</li>
<li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li>
</ul> </ul>
</div> </div>
</div> </div>

View file

@ -1,11 +1,17 @@
<template> <template>
<basic-user-card :user="user"> <basic-user-card :user="user">
<div class="follow-card-content-container"> <div class="follow-card-content-container">
<span class="faint" v-if="!noFollowsYou && user.follows_you"> <span
v-if="!noFollowsYou && user.follows_you"
class="faint"
>
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }} {{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
</span> </span>
<template v-if="!loggedIn"> <template v-if="!loggedIn">
<div class="follow-card-follow-button" v-if="!user.following"> <div
v-if="!user.following"
class="follow-card-follow-button"
>
<RemoteFollow :user="user" /> <RemoteFollow :user="user" />
</div> </div>
</template> </template>
@ -13,9 +19,9 @@
<button <button
v-if="!user.following" v-if="!user.following"
class="btn btn-default follow-card-follow-button" class="btn btn-default follow-card-follow-button"
@click="followUser"
:disabled="inProgress" :disabled="inProgress"
:title="requestSent ? $t('user_card.follow_again') : ''" :title="requestSent ? $t('user_card.follow_again') : ''"
@click="followUser"
> >
<template v-if="inProgress"> <template v-if="inProgress">
{{ $t('user_card.follow_progress') }} {{ $t('user_card.follow_progress') }}
@ -27,7 +33,12 @@
{{ $t('user_card.follow') }} {{ $t('user_card.follow') }}
</template> </template>
</button> </button>
<button v-else class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress"> <button
v-else
class="btn btn-default follow-card-follow-button pressed"
:disabled="inProgress"
@click="unfollowUser"
>
<template v-if="inProgress"> <template v-if="inProgress">
{{ $t('user_card.follow_progress') }} {{ $t('user_card.follow_progress') }}
</template> </template>

View file

@ -1,8 +1,18 @@
<template> <template>
<basic-user-card :user="user"> <basic-user-card :user="user">
<div class="follow-request-card-content-container"> <div class="follow-request-card-content-container">
<button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button> <button
<button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button> class="btn btn-default"
@click="approveUser"
>
{{ $t('user_card.approve') }}
</button>
<button
class="btn btn-default"
@click="denyUser"
>
{{ $t('user_card.deny') }}
</button>
</div> </div>
</basic-user-card> </basic-user-card>
</template> </template>

View file

@ -1,10 +1,15 @@
<template> <template>
<div class="settings panel panel-default"> <div class="settings panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{$t('nav.friend_requests')}} {{ $t('nav.friend_requests') }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<FollowRequestCard v-for="request in requests" :key="request.id" :user="request" class="list-item"/> <FollowRequestCard
v-for="request in requests"
:key="request.id"
:user="request"
class="list-item"
/>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,35 +1,55 @@
<template> <template>
<div class="font-control style-control" :class="{ custom: isCustom }"> <div
<label :for="preset === 'custom' ? name : name + '-font-switcher'" class="label"> class="font-control style-control"
{{label}} :class="{ custom: isCustom }"
</label> >
<input <label
v-if="typeof fallback !== 'undefined'" :for="preset === 'custom' ? name : name + '-font-switcher'"
class="opt exlcude-disabled" class="label"
type="checkbox" >
:id="name + '-o'" {{ label }}
:checked="present" </label>
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)"> <input
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label> v-if="typeof fallback !== 'undefined'"
<label :for="name + '-font-switcher'" class="select" :disabled="!present"> :id="name + '-o'"
<select class="opt exlcude-disabled"
type="checkbox"
:checked="present"
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)"
>
<label
v-if="typeof fallback !== 'undefined'"
class="opt-l"
:for="name + '-o'"
/>
<label
:for="name + '-font-switcher'"
class="select"
:disabled="!present" :disabled="!present"
v-model="preset" >
class="font-switcher" <select
:id="name + '-font-switcher'"> :id="name + '-font-switcher'"
<option v-for="option in availableOptions" :value="option"> v-model="preset"
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }} :disabled="!present"
</option> class="font-switcher"
</select> >
<i class="icon-down-open"/> <option
</label> v-for="option in availableOptions"
<input :value="option"
v-if="isCustom" >
class="custom-font" {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
type="text" </option>
:id="name" </select>
v-model="family"> <i class="icon-down-open" />
</div> </label>
<input
v-if="isCustom"
:id="name"
v-model="family"
class="custom-font"
type="text"
>
</div>
</template> </template>
<script src="./font_control.js" ></script> <script src="./font_control.js" ></script>

View file

@ -1,5 +1,9 @@
<template> <template>
<Timeline :title="$t('nav.timeline')" v-bind:timeline="timeline" v-bind:timeline-name="'friends'"/> <Timeline
:title="$t('nav.timeline')"
:timeline="timeline"
:timeline-name="'friends'"
/>
</template> </template>
<script src="./friends_timeline.js"></script> <script src="./friends_timeline.js"></script>

View file

@ -1,13 +1,21 @@
<template> <template>
<div ref="galleryContainer" style="width: 100%;"> <div
<div class="gallery-row" v-for="row in rows" :style="rowHeight(row.length)" :class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"> ref="galleryContainer"
style="width: 100%;"
>
<div
v-for="row in rows"
class="gallery-row"
:style="rowHeight(row.length)"
:class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"
>
<attachment <attachment
v-for="attachment in row" v-for="attachment in row"
:setMedia="setMedia" :key="attachment.id"
:set-media="setMedia"
:nsfw="nsfw" :nsfw="nsfw"
:attachment="attachment" :attachment="attachment"
:allowPlay="false" :allow-play="false"
:key="attachment.id"
/> />
</div> </div>
</div> </div>

View file

@ -2,20 +2,57 @@
<div class="image-cropper"> <div class="image-cropper">
<div v-if="dataUrl"> <div v-if="dataUrl">
<div class="image-cropper-image-container"> <div class="image-cropper-image-container">
<img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" /> <img
ref="img"
:src="dataUrl"
alt=""
@load.stop="createCropper"
>
</div> </div>
<div class="image-cropper-buttons-wrapper"> <div class="image-cropper-buttons-wrapper">
<button class="btn" type="button" :disabled="submitting" @click="submit()" v-text="saveText"></button> <button
<button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button> class="btn"
<button class="btn" type="button" :disabled="submitting" @click="submit(false)" v-text="saveWithoutCroppingText"></button> type="button"
<i class="icon-spin4 animate-spin" v-if="submitting"></i> :disabled="submitting"
@click="submit()"
v-text="saveText"
/>
<button
class="btn"
type="button"
:disabled="submitting"
@click="destroy"
v-text="cancelText"
/>
<button
class="btn"
type="button"
:disabled="submitting"
@click="submit(false)"
v-text="saveWithoutCroppingText"
/>
<i
v-if="submitting"
class="icon-spin4 animate-spin"
/>
</div> </div>
<div class="alert error" v-if="submitError"> <div
{{submitErrorMsg}} v-if="submitError"
<i class="button-icon icon-cancel" @click="clearError"></i> class="alert error"
>
{{ submitErrorMsg }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div> </div>
</div> </div>
<input ref="input" type="file" class="image-cropper-img-input" :accept="mimes"> <input
ref="input"
type="file"
class="image-cropper-img-input"
:accept="mimes"
>
</div> </div>
</template> </template>

View file

@ -1,17 +1,36 @@
<template> <template>
<div class="importer"> <div class="importer">
<form> <form>
<input type="file" ref="input" v-on:change="change" /> <input
ref="input"
type="file"
@change="change"
>
</form> </form>
<i class="icon-spin4 animate-spin importer-uploading" v-if="submitting"></i> <i
<button class="btn btn-default" v-else @click="submit">{{submitButtonLabel}}</button> v-if="submitting"
class="icon-spin4 animate-spin importer-uploading"
/>
<button
v-else
class="btn btn-default"
@click="submit"
>
{{ submitButtonLabel }}
</button>
<div v-if="success"> <div v-if="success">
<i class="icon-cross" @click="dismiss"></i> <i
<p>{{successMessage}}</p> class="icon-cross"
@click="dismiss"
/>
<p>{{ successMessage }}</p>
</div> </div>
<div v-else-if="error"> <div v-else-if="error">
<i class="icon-cross" @click="dismiss"></i> <i
<p>{{errorMessage}}</p> class="icon-cross"
@click="dismiss"
/>
<p>{{ errorMessage }}</p>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,9 +1,11 @@
<template> <template>
<div v-if="show" class="instance-specific-panel"> <div
v-if="show"
class="instance-specific-panel"
>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body"> <div class="panel-body">
<div v-html="instanceSpecificPanelContent"> <div v-html="instanceSpecificPanelContent" />
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -7,18 +7,30 @@
</div> </div>
<tab-switcher <tab-switcher
ref="tabSwitcher" ref="tabSwitcher"
:onSwitch="onModeSwitch" :on-switch="onModeSwitch"
> >
<span data-tab-dummy data-filter="mentions" :label="$t('nav.mentions')"/> <span
<span data-tab-dummy data-filter="likes+repeats" :label="$t('interactions.favs_repeats')"/> data-tab-dummy
<span data-tab-dummy data-filter="follows" :label="$t('interactions.follows')"/> data-filter="mentions"
:label="$t('nav.mentions')"
/>
<span
data-tab-dummy
data-filter="likes+repeats"
:label="$t('interactions.favs_repeats')"
/>
<span
data-tab-dummy
data-filter="follows"
:label="$t('interactions.follows')"
/>
</tab-switcher> </tab-switcher>
<Notifications <Notifications
ref="notifications" ref="notifications"
:noHeading="true" :no-heading="true"
:minimalMode="true" :minimal-mode="true"
:filterMode="filterMode" :filter-mode="filterMode"
/> />
</div> </div>
</template> </template>

View file

@ -3,50 +3,59 @@
<label for="interface-language-switcher"> <label for="interface-language-switcher">
{{ $t('settings.interfaceLanguage') }} {{ $t('settings.interfaceLanguage') }}
</label> </label>
<label for="interface-language-switcher" class='select'> <label
<select id="interface-language-switcher" v-model="language"> for="interface-language-switcher"
<option v-for="(langCode, i) in languageCodes" :value="langCode"> class="select"
>
<select
id="interface-language-switcher"
v-model="language"
>
<option
v-for="(langCode, i) in languageCodes"
:value="langCode"
>
{{ languageNames[i] }} {{ languageNames[i] }}
</option> </option>
</select> </select>
<i class="icon-down-open"/> <i class="icon-down-open" />
</label> </label>
</div> </div>
</template> </template>
<script> <script>
import languagesObject from '../../i18n/messages' import languagesObject from '../../i18n/messages'
import ISO6391 from 'iso-639-1' import ISO6391 from 'iso-639-1'
import _ from 'lodash' import _ from 'lodash'
export default { export default {
computed: { computed: {
languageCodes () { languageCodes () {
return Object.keys(languagesObject) return Object.keys(languagesObject)
},
languageNames () {
return _.map(this.languageCodes, this.getLanguageName)
},
language: {
get: function () { return this.$store.state.config.interfaceLanguage },
set: function (val) {
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
this.$i18n.locale = val
}
}
}, },
methods: { languageNames () {
getLanguageName (code) { return _.map(this.languageCodes, this.getLanguageName)
const specialLanguageNames = { },
'ja': 'Japanese (やさしいにほんご)',
'ja_pedantic': 'Japanese (日本語)', language: {
'zh': 'Chinese (简体中文)' get: function () { return this.$store.state.config.interfaceLanguage },
} set: function (val) {
return specialLanguageNames[code] || ISO6391.getName(code) this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
this.$i18n.locale = val
} }
} }
},
methods: {
getLanguageName (code) {
const specialLanguageNames = {
'ja': 'Japanese (やさしいにほんご)',
'ja_pedantic': 'Japanese (日本語)',
'zh': 'Chinese (简体中文)'
}
return specialLanguageNames[code] || ISO6391.getName(code)
}
} }
}
</script> </script>

View file

@ -1,13 +1,25 @@
<template> <template>
<div> <div>
<a class="link-preview-card" :href="card.url" target="_blank" rel="noopener"> <a
<div class="card-image" :class="{ 'small-image': size === 'small' }" v-if="useImage"> class="link-preview-card"
:href="card.url"
target="_blank"
rel="noopener"
>
<div
v-if="useImage"
class="card-image"
:class="{ 'small-image': size === 'small' }"
>
<img :src="card.image"></img> <img :src="card.image"></img>
</div> </div>
<div class="card-content"> <div class="card-content">
<span class="card-host faint">{{ card.provider_name }}</span> <span class="card-host faint">{{ card.provider_name }}</span>
<h4 class="card-title">{{ card.title }}</h4> <h4 class="card-title">{{ card.title }}</h4>
<p class="card-description" v-if="useDescription">{{ card.description }}</p> <p
v-if="useDescription"
class="card-description"
>{{ card.description }}</p>
</div> </div>
</a> </a>
</div> </div>

View file

@ -1,9 +1,19 @@
<template> <template>
<div class="list"> <div class="list">
<div v-for="item in items" class="list-item" :key="getKey(item)"> <div
<slot name="item" :item="item" /> v-for="item in items"
:key="getKey(item)"
class="list-item"
>
<slot
name="item"
:item="item"
/>
</div> </div>
<div class="list-empty-content faint" v-if="items.length === 0 && !!$slots.empty"> <div
v-if="items.length === 0 && !!$slots.empty"
class="list-empty-content faint"
>
<slot name="empty" /> <slot name="empty" />
</div> </div>
</div> </div>

View file

@ -1,53 +1,83 @@
<template> <template>
<div class="login panel panel-default"> <div class="login panel panel-default">
<!-- Default panel contents --> <!-- Default panel contents -->
<div class="panel-heading">{{$t('login.login')}}</div> <div class="panel-heading">
{{ $t('login.login') }}
</div>
<div class="panel-body"> <div class="panel-body">
<form class='login-form' @submit.prevent='submit'> <form
<template v-if="isPasswordAuth"> class="login-form"
<div class='form-group'> @submit.prevent="submit"
<label for='username'>{{$t('login.username')}}</label> >
<input :disabled="loggingIn" v-model='user.username' <template v-if="isPasswordAuth">
class='form-control' id='username' <div class="form-group">
:placeholder="$t('login.placeholder')"> <label for="username">{{ $t('login.username') }}</label>
</div> <input
<div class='form-group'> id="username"
<label for='password'>{{$t('login.password')}}</label> v-model="user.username"
<input :disabled="loggingIn" v-model='user.password' :disabled="loggingIn"
ref='passwordInput' class='form-control' id='password' type='password'> class="form-control"
</div> :placeholder="$t('login.placeholder')"
</template> >
<div class="form-group" v-if="isTokenAuth">
<p>{{$t('login.description')}}</p>
</div>
<div class='form-group'>
<div class='login-bottom'>
<div>
<router-link :to="{name: 'registration'}"
v-if='registrationOpen'
class='register'>
{{$t('login.register')}}
</router-link>
</div> </div>
<button :disabled="loggingIn" type='submit' class='btn btn-default'> <div class="form-group">
{{$t('login.login')}} <label for="password">{{ $t('login.password') }}</label>
</button> <input
</div> id="password"
</div> ref="passwordInput"
</form> v-model="user.password"
</div> :disabled="loggingIn"
class="form-control"
type="password"
>
</div>
</template>
<div v-if="error" class='form-group'> <div
<div class='alert error'> v-if="isTokenAuth"
{{error}} class="form-group"
<i class="button-icon icon-cancel" @click="clearError"></i> >
<p>{{ $t('login.description') }}</p>
</div>
<div class="form-group">
<div class="login-bottom">
<div>
<router-link
v-if="registrationOpen"
:to="{name: 'registration'}"
class="register"
>
{{ $t('login.register') }}
</router-link>
</div>
<button
:disabled="loggingIn"
type="submit"
class="btn btn-default"
>
{{ $t('login.login') }}
</button>
</div>
</div>
</form>
</div>
<div
v-if="error"
class="form-group"
>
<div class="alert error">
{{ error }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script src="./login_form.js" ></script> <script src="./login_form.js" ></script>

View file

@ -1,25 +1,33 @@
<template> <template>
<div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide"> <div
<img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img> v-if="showing"
<VideoAttachment class="modal-view media-modal-view"
@click.prevent="hide"
>
<img
v-if="type === 'image'"
class="modal-image" class="modal-image"
:src="currentMedia.url"
></img>
<VideoAttachment
v-if="type === 'video'" v-if="type === 'video'"
class="modal-image"
:attachment="currentMedia" :attachment="currentMedia"
:controls="true" :controls="true"
@click.stop.native=""> @click.stop.native=""
</VideoAttachment> />
<button <button
v-if="canNavigate"
:title="$t('media_modal.previous')" :title="$t('media_modal.previous')"
class="modal-view-button-arrow modal-view-button-arrow--prev" class="modal-view-button-arrow modal-view-button-arrow--prev"
v-if="canNavigate"
@click.stop.prevent="goPrev" @click.stop.prevent="goPrev"
> >
<i class="icon-left-open arrow-icon" /> <i class="icon-left-open arrow-icon" />
</button> </button>
<button <button
v-if="canNavigate"
:title="$t('media_modal.next')" :title="$t('media_modal.next')"
class="modal-view-button-arrow modal-view-button-arrow--next" class="modal-view-button-arrow modal-view-button-arrow--next"
v-if="canNavigate"
@click.stop.prevent="goNext" @click.stop.prevent="goNext"
> >
<i class="icon-right-open arrow-icon" /> <i class="icon-right-open arrow-icon" />

View file

@ -1,9 +1,29 @@
<template> <template>
<div class="media-upload" @drop.prevent @dragover.prevent="fileDrag" @drop="fileDrop"> <div
<label class="btn btn-default" :title="$t('tool_tip.media_upload')"> class="media-upload"
<i class="icon-spin4 animate-spin" v-if="uploading"></i> @drop.prevent
<i class="icon-upload" v-if="!uploading"></i> @dragover.prevent="fileDrag"
<input type="file" v-if="uploadReady" @change="change" style="position: fixed; top: -100em" multiple="true"></input> @drop="fileDrop"
>
<label
class="btn btn-default"
:title="$t('tool_tip.media_upload')"
>
<i
v-if="uploading"
class="icon-spin4 animate-spin"
/>
<i
v-if="!uploading"
class="icon-upload"
/>
<input
v-if="uploadReady"
type="file"
style="position: fixed; top: -100em"
multiple="true"
@change="change"
></input>
</label> </label>
</div> </div>
</template> </template>

View file

@ -1,5 +1,9 @@
<template> <template>
<Timeline :title="$t('nav.interactions')" v-bind:timeline="timeline" v-bind:timeline-name="'mentions'"/> <Timeline
:title="$t('nav.interactions')"
:timeline="timeline"
:timeline-name="'mentions'"
/>
</template> </template>
<script src="./mentions.js"></script> <script src="./mentions.js"></script>

View file

@ -1,42 +1,65 @@
<template> <template>
<div class="login panel panel-default"> <div class="login panel panel-default">
<!-- Default panel contents --> <!-- Default panel contents -->
<div class="panel-heading">{{$t('login.heading.recovery')}}</div> <div class="panel-heading">
{{ $t('login.heading.recovery') }}
</div>
<div class="panel-body"> <div class="panel-body">
<form class='login-form' @submit.prevent='submit'> <form
<div class='form-group'> class="login-form"
<label for='code'>{{$t('login.recovery_code')}}</label> @submit.prevent="submit"
<input v-model='code' class='form-control' id='code'> >
</div> <div class="form-group">
<label for="code">{{ $t('login.recovery_code') }}</label>
<div class='form-group'> <input
<div class='login-bottom'> id="code"
<div> v-model="code"
<a href="#" @click.prevent="requireTOTP"> class="form-control"
{{$t('login.enter_two_factor_code')}} >
</a>
<br />
<a href="#" @click.prevent="abortMFA">
{{$t('general.cancel')}}
</a>
</div>
<button type='submit' class='btn btn-default'>
{{$t('general.verify')}}
</button>
</div> </div>
<div class="form-group">
<div class="login-bottom">
<div>
<a
href="#"
@click.prevent="requireTOTP"
>
{{ $t('login.enter_two_factor_code') }}
</a>
<br>
<a
href="#"
@click.prevent="abortMFA"
>
{{ $t('general.cancel') }}
</a>
</div>
<button
type="submit"
class="btn btn-default"
>
{{ $t('general.verify') }}
</button>
</div>
</div>
</form>
</div>
<div
v-if="error"
class="form-group"
>
<div class="alert error">
{{ error }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div> </div>
</form>
</div>
<div v-if="error" class='form-group'>
<div class='alert error'>
{{error}}
<i class="button-icon icon-cancel" @click="clearError"></i>
</div> </div>
</div> </div>
</div>
</template> </template>
<script src="./recovery_form.js" ></script> <script src="./recovery_form.js" ></script>

View file

@ -1,45 +1,67 @@
<template> <template>
<div class="login panel panel-default"> <div class="login panel panel-default">
<!-- Default panel contents --> <!-- Default panel contents -->
<div class="panel-heading"> <div class="panel-heading">
{{$t('login.heading.totp')}} {{ $t('login.heading.totp') }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form class='login-form' @submit.prevent='submit'> <form
<div class='form-group'> class="login-form"
<label for='code'> @submit.prevent="submit"
{{$t('login.authentication_code')}} >
</label> <div class="form-group">
<input v-model='code' class='form-control' id='code'> <label for="code">
</div> {{ $t('login.authentication_code') }}
</label>
<div class='form-group'> <input
<div class='login-bottom'> id="code"
<div> v-model="code"
<a href="#" @click.prevent="requireRecovery"> class="form-control"
{{$t('login.enter_recovery_code')}} >
</a>
<br />
<a href="#" @click.prevent="abortMFA">
{{$t('general.cancel')}}
</a>
</div>
<button type='submit' class='btn btn-default'>
{{$t('general.verify')}}
</button>
</div> </div>
</div>
</form>
</div>
<div v-if="error" class='form-group'> <div class="form-group">
<div class='alert error'> <div class="login-bottom">
{{error}} <div>
<i class="button-icon icon-cancel" @click="clearError"></i> <a
href="#"
@click.prevent="requireRecovery"
>
{{ $t('login.enter_recovery_code') }}
</a>
<br>
<a
href="#"
@click.prevent="abortMFA"
>
{{ $t('general.cancel') }}
</a>
</div>
<button
type="submit"
class="btn btn-default"
>
{{ $t('general.verify') }}
</button>
</div>
</div>
</form>
</div>
<div
v-if="error"
class="form-group"
>
<div class="alert error">
{{ error }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script src="./totp_form.js"></script> <script src="./totp_form.js"></script>

View file

@ -1,38 +1,75 @@
<template> <template>
<div> <div>
<nav class='nav-bar container' id="nav"> <nav
<div class='mobile-inner-nav' @click="scrollToTop()"> id="nav"
<div class='item'> class="nav-bar container"
<a href="#" class="mobile-nav-button" @click.stop.prevent="toggleMobileSidebar()"> >
<i class="button-icon icon-menu"></i> <div
class="mobile-inner-nav"
@click="scrollToTop()"
>
<div class="item">
<a
href="#"
class="mobile-nav-button"
@click.stop.prevent="toggleMobileSidebar()"
>
<i class="button-icon icon-menu" />
</a> </a>
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link> <router-link
class="site-name"
:to="{ name: 'root' }"
active-class="home"
>
{{ sitename }}
</router-link>
</div> </div>
<div class='item right'> <div class="item right">
<a class="mobile-nav-button" v-if="currentUser" href="#" @click.stop.prevent="openMobileNotifications()"> <a
<i class="button-icon icon-bell-alt"></i> v-if="currentUser"
<div class="alert-dot" v-if="unseenNotificationsCount"></div> class="mobile-nav-button"
href="#"
@click.stop.prevent="openMobileNotifications()"
>
<i class="button-icon icon-bell-alt" />
<div
v-if="unseenNotificationsCount"
class="alert-dot"
/>
</a> </a>
</div> </div>
</div> </div>
</nav> </nav>
<div v-if="currentUser" <div
v-if="currentUser"
class="mobile-notifications-drawer" class="mobile-notifications-drawer"
:class="{ 'closed': !notificationsOpen }" :class="{ 'closed': !notificationsOpen }"
@touchstart.stop="notificationsTouchStart" @touchstart.stop="notificationsTouchStart"
@touchmove.stop="notificationsTouchMove" @touchmove.stop="notificationsTouchMove"
> >
<div class="mobile-notifications-header"> <div class="mobile-notifications-header">
<span class="title">{{$t('notifications.notifications')}}</span> <span class="title">{{ $t('notifications.notifications') }}</span>
<a class="mobile-nav-button" @click.stop.prevent="closeMobileNotifications()"> <a
<i class="button-icon icon-cancel"/> class="mobile-nav-button"
@click.stop.prevent="closeMobileNotifications()"
>
<i class="button-icon icon-cancel" />
</a> </a>
</div> </div>
<div class="mobile-notifications" @scroll="onScroll"> <div
<Notifications ref="notifications" :noHeading="true"/> class="mobile-notifications"
@scroll="onScroll"
>
<Notifications
ref="notifications"
:no-heading="true"
/>
</div> </div>
</div> </div>
<SideDrawer ref="sideDrawer" :logout="logout"/> <SideDrawer
ref="sideDrawer"
:logout="logout"
/>
<MobilePostStatusModal /> <MobilePostStatusModal />
</div> </div>
</template> </template>

View file

@ -1,23 +1,31 @@
<template> <template>
<div v-if="currentUser"> <div v-if="currentUser">
<div <div
class="post-form-modal-view modal-view" v-show="postFormOpen"
v-show="postFormOpen" class="post-form-modal-view modal-view"
@click="closePostForm" @click="closePostForm"
> >
<div class="post-form-modal-panel panel" @click.stop=""> <div
<div class="panel-heading">{{$t('post_status.new_status')}}</div> class="post-form-modal-panel panel"
<PostStatusForm class="panel-body" @posted="closePostForm" /> @click.stop=""
>
<div class="panel-heading">
{{ $t('post_status.new_status') }}
</div>
<PostStatusForm
class="panel-body"
@posted="closePostForm"
/>
</div>
</div> </div>
<button
class="new-status-button"
:class="{ 'hidden': isHidden }"
@click="openPostForm"
>
<i class="icon-edit" />
</button>
</div> </div>
<button
class="new-status-button"
:class="{ 'hidden': isHidden }"
@click="openPostForm"
>
<i class="icon-edit" />
</button>
</div>
</template> </template>
<script src="./mobile_post_status_modal.js"></script> <script src="./mobile_post_status_modal.js"></script>

View file

@ -1,85 +1,168 @@
<template> <template>
<div class='block' style='position: relative'> <div
<Popper class="block"
trigger="click" style="position: relative"
@hide='showDropDown = false' >
append-to-body <Popper
:options="{ trigger="click"
placement: 'bottom-end', append-to-body
modifiers: { :options="{
arrow: { enabled: true }, placement: 'bottom-end',
offset: { offset: '0, 5px' }, modifiers: {
} arrow: { enabled: true },
}"> offset: { offset: '0, 5px' },
<div class="popper-wrapper"> }
<div class="dropdown-menu"> }"
<span v-if='user.is_local'> @hide="showDropDown = false"
<button class="dropdown-item" @click='toggleRight("admin")'> >
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }} <div class="popper-wrapper">
<div class="dropdown-menu">
<span v-if="user.is_local">
<button
class="dropdown-item"
@click="toggleRight(&quot;admin&quot;)"
>
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
</button>
<button
class="dropdown-item"
@click="toggleRight(&quot;moderator&quot;)"
>
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
</button>
<div
role="separator"
class="dropdown-divider"
/>
</span>
<button
class="dropdown-item"
@click="toggleActivationStatus()"
>
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
</button> </button>
<button class="dropdown-item" @click='toggleRight("moderator")'> <button
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }} class="dropdown-item"
@click="deleteUserDialog(true)"
>
{{ $t('user_card.admin_menu.delete_account') }}
</button> </button>
<div role="separator" class="dropdown-divider"></div> <div
</span> v-if="hasTagPolicy"
<button class="dropdown-item" @click='toggleActivationStatus()'> role="separator"
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }} class="dropdown-divider"
</button> />
<button class="dropdown-item" @click='deleteUserDialog(true)'> <span v-if="hasTagPolicy">
{{ $t('user_card.admin_menu.delete_account') }} <button
</button> class="dropdown-item"
<div role="separator" class="dropdown-divider" v-if='hasTagPolicy'></div> @click="toggleTag(tags.FORCE_NSFW)"
<span v-if='hasTagPolicy'> >
<button class="dropdown-item" @click='toggleTag(tags.FORCE_NSFW)'> {{ $t('user_card.admin_menu.force_nsfw') }}
{{ $t('user_card.admin_menu.force_nsfw') }} <span
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"></span> class="menu-checkbox"
</button> :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"
<button class="dropdown-item" @click='toggleTag(tags.STRIP_MEDIA)'> />
{{ $t('user_card.admin_menu.strip_media') }} </button>
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"></span> <button
</button> class="dropdown-item"
<button class="dropdown-item" @click='toggleTag(tags.FORCE_UNLISTED)'> @click="toggleTag(tags.STRIP_MEDIA)"
{{ $t('user_card.admin_menu.force_unlisted') }} >
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"></span> {{ $t('user_card.admin_menu.strip_media') }}
</button> <span
<button class="dropdown-item" @click='toggleTag(tags.SANDBOX)'> class="menu-checkbox"
{{ $t('user_card.admin_menu.sandbox') }} :class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"></span> />
</button> </button>
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)'> <button
{{ $t('user_card.admin_menu.disable_remote_subscription') }} class="dropdown-item"
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"></span> @click="toggleTag(tags.FORCE_UNLISTED)"
</button> >
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)'> {{ $t('user_card.admin_menu.force_unlisted') }}
{{ $t('user_card.admin_menu.disable_any_subscription') }} <span
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"></span> class="menu-checkbox"
</button> :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.QUARANTINE)'> />
{{ $t('user_card.admin_menu.quarantine') }} </button>
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"></span> <button
</button> class="dropdown-item"
</span> @click="toggleTag(tags.SANDBOX)"
>
{{ $t('user_card.admin_menu.sandbox') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"
/>
</button>
<button
v-if="user.is_local"
class="dropdown-item"
@click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)"
>
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"
/>
</button>
<button
v-if="user.is_local"
class="dropdown-item"
@click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)"
>
{{ $t('user_card.admin_menu.disable_any_subscription') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"
/>
</button>
<button
v-if="user.is_local"
class="dropdown-item"
@click="toggleTag(tags.QUARANTINE)"
>
{{ $t('user_card.admin_menu.quarantine') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"
/>
</button>
</span>
</div>
</div> </div>
</div> <button
<button slot="reference" v-bind:class="{ pressed: showDropDown }" @click='toggleMenu'> slot="reference"
{{ $t('user_card.admin_menu.moderation') }} :class="{ pressed: showDropDown }"
</button> @click="toggleMenu"
</Popper> >
<portal to="modal"> {{ $t('user_card.admin_menu.moderation') }}
<DialogModal v-if="showDeleteUserDialog" :onCancel='deleteUserDialog.bind(this, false)'> </button>
<template slot="header">{{ $t('user_card.admin_menu.delete_user') }}</template> </Popper>
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p> <portal to="modal">
<template slot="footer"> <DialogModal
<button class="btn btn-default" @click='deleteUserDialog(false)'> v-if="showDeleteUserDialog"
{{ $t('general.cancel') }} :on-cancel="deleteUserDialog.bind(this, false)"
</button> >
<button class="btn btn-default danger" @click='deleteUser()'> <template slot="header">
{{ $t('user_card.admin_menu.delete_user') }} {{ $t('user_card.admin_menu.delete_user') }}
</button> </template>
</template> <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
</DialogModal> <template slot="footer">
</portal> <button
</div> class="btn btn-default"
@click="deleteUserDialog(false)"
>
{{ $t('general.cancel') }}
</button>
<button
class="btn btn-default danger"
@click="deleteUser()"
>
{{ $t('user_card.admin_menu.delete_user') }}
</button>
</template>
</DialogModal>
</portal>
</div>
</template> </template>
<script src="./moderation_tools.js"></script> <script src="./moderation_tools.js"></script>

View file

@ -1,7 +1,12 @@
<template> <template>
<basic-user-card :user="user"> <basic-user-card :user="user">
<div class="mute-card-content-container"> <div class="mute-card-content-container">
<button class="btn btn-default" @click="unmuteUser" :disabled="progress" v-if="muted"> <button
v-if="muted"
class="btn btn-default"
:disabled="progress"
@click="unmuteUser"
>
<template v-if="progress"> <template v-if="progress">
{{ $t('user_card.unmute_progress') }} {{ $t('user_card.unmute_progress') }}
</template> </template>
@ -9,7 +14,12 @@
{{ $t('user_card.unmute') }} {{ $t('user_card.unmute') }}
</template> </template>
</button> </button>
<button class="btn btn-default" @click="muteUser" :disabled="progress" v-else> <button
v-else
class="btn btn-default"
:disabled="progress"
@click="muteUser"
>
<template v-if="progress"> <template v-if="progress">
{{ $t('user_card.mute_progress') }} {{ $t('user_card.mute_progress') }}
</template> </template>

View file

@ -2,26 +2,29 @@
<div class="nav-panel"> <div class="nav-panel">
<div class="panel panel-default"> <div class="panel panel-default">
<ul> <ul>
<li v-if='currentUser'> <li v-if="currentUser">
<router-link :to="{ name: 'friends' }"> <router-link :to="{ name: 'friends' }">
{{ $t("nav.timeline") }} {{ $t("nav.timeline") }}
</router-link> </router-link>
</li> </li>
<li v-if='currentUser'> <li v-if="currentUser">
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
{{ $t("nav.interactions") }} {{ $t("nav.interactions") }}
</router-link> </router-link>
</li> </li>
<li v-if='currentUser'> <li v-if="currentUser">
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
{{ $t("nav.dms") }} {{ $t("nav.dms") }}
</router-link> </router-link>
</li> </li>
<li v-if='currentUser && currentUser.locked'> <li v-if="currentUser && currentUser.locked">
<router-link :to="{ name: 'friend-requests' }"> <router-link :to="{ name: 'friend-requests' }">
{{ $t("nav.friend_requests")}} {{ $t("nav.friend_requests") }}
<span v-if='followRequestCount > 0' class="badge follow-request-count"> <span
{{followRequestCount}} v-if="followRequestCount > 0"
class="badge follow-request-count"
>
{{ followRequestCount }}
</span> </span>
</router-link> </router-link>
</li> </li>

View file

@ -3,49 +3,102 @@
v-if="notification.type === 'mention'" v-if="notification.type === 'mention'"
:compact="true" :compact="true"
:statusoid="notification.status" :statusoid="notification.status"
/>
<div
v-else
class="non-mention"
:class="[userClass, { highlighted: userStyle }]"
:style="[ userStyle ]"
> >
</status> <a
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]" v-else> class="avatar-container"
<a class='avatar-container' :href="notification.from_profile.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded"> :href="notification.from_profile.statusnet_profile_url"
<UserAvatar :compact="true" :betterShadow="betterShadow" :user="notification.from_profile"/> @click.stop.prevent.capture="toggleUserExpanded"
>
<UserAvatar
:compact="true"
:better-shadow="betterShadow"
:user="notification.from_profile"
/>
</a> </a>
<div class='notification-right'> <div class="notification-right">
<UserCard :user="getUser(notification)" :rounded="true" :bordered="true" v-if="userExpanded" /> <UserCard
v-if="userExpanded"
:user="getUser(notification)"
:rounded="true"
:bordered="true"
/>
<span class="notification-details"> <span class="notification-details">
<div class="name-and-action"> <div class="name-and-action">
<span class="username" v-if="!!notification.from_profile.name_html" :title="'@'+notification.from_profile.screen_name" v-html="notification.from_profile.name_html"></span> <span
<span class="username" v-else :title="'@'+notification.from_profile.screen_name">{{ notification.from_profile.name }}</span> v-if="!!notification.from_profile.name_html"
class="username"
:title="'@'+notification.from_profile.screen_name"
v-html="notification.from_profile.name_html"
/>
<span
v-else
class="username"
:title="'@'+notification.from_profile.screen_name"
>{{ notification.from_profile.name }}</span>
<span v-if="notification.type === 'like'"> <span v-if="notification.type === 'like'">
<i class="fa icon-star lit"></i> <i class="fa icon-star lit" />
<small>{{$t('notifications.favorited_you')}}</small> <small>{{ $t('notifications.favorited_you') }}</small>
</span> </span>
<span v-if="notification.type === 'repeat'"> <span v-if="notification.type === 'repeat'">
<i class="fa icon-retweet lit" :title="$t('tool_tip.repeat')"></i> <i
<small>{{$t('notifications.repeated_you')}}</small> class="fa icon-retweet lit"
:title="$t('tool_tip.repeat')"
/>
<small>{{ $t('notifications.repeated_you') }}</small>
</span> </span>
<span v-if="notification.type === 'follow'"> <span v-if="notification.type === 'follow'">
<i class="fa icon-user-plus lit"></i> <i class="fa icon-user-plus lit" />
<small>{{$t('notifications.followed_you')}}</small> <small>{{ $t('notifications.followed_you') }}</small>
</span> </span>
</div> </div>
<div class="timeago" v-if="notification.type === 'follow'"> <div
v-if="notification.type === 'follow'"
class="timeago"
>
<span class="faint"> <span class="faint">
<Timeago :time="notification.created_at" :auto-update="240"></Timeago> <Timeago
:time="notification.created_at"
:auto-update="240"
/>
</span> </span>
</div> </div>
<div class="timeago" v-else> <div
<router-link v-if="notification.status" :to="{ name: 'conversation', params: { id: notification.status.id } }" class="faint-link"> v-else
<Timeago :time="notification.created_at" :auto-update="240"></Timeago> class="timeago"
>
<router-link
v-if="notification.status"
:to="{ name: 'conversation', params: { id: notification.status.id } }"
class="faint-link"
>
<Timeago
:time="notification.created_at"
:auto-update="240"
/>
</router-link> </router-link>
</div> </div>
</span> </span>
<div class="follow-text" v-if="notification.type === 'follow'"> <div
v-if="notification.type === 'follow'"
class="follow-text"
>
<router-link :to="userProfileLink(notification.from_profile)"> <router-link :to="userProfileLink(notification.from_profile)">
@{{notification.from_profile.screen_name}} @{{ notification.from_profile.screen_name }}
</router-link> </router-link>
</div> </div>
<template v-else> <template v-else>
<status class="faint" :compact="true" :statusoid="notification.action" :noHeading="true"></status> <status
class="faint"
:compact="true"
:statusoid="notification.action"
:no-heading="true"
/>
</template> </template>
</div> </div>
</div> </div>

View file

@ -1,33 +1,67 @@
<template> <template>
<div :class="{ minimal: minimalMode }" class="notifications"> <div
:class="{ minimal: minimalMode }"
class="notifications"
>
<div :class="mainClass"> <div :class="mainClass">
<div v-if="!noHeading" class="panel-heading"> <div
v-if="!noHeading"
class="panel-heading"
>
<div class="title"> <div class="title">
{{$t('notifications.notifications')}} {{ $t('notifications.notifications') }}
<span class="badge badge-notification unseen-count" v-if="unseenCount">{{unseenCount}}</span> <span
v-if="unseenCount"
class="badge badge-notification unseen-count"
>{{ unseenCount }}</span>
</div> </div>
<div @click.prevent class="loadmore-error alert error" v-if="error"> <div
{{$t('timeline.error_fetching')}} v-if="error"
class="loadmore-error alert error"
@click.prevent
>
{{ $t('timeline.error_fetching') }}
</div> </div>
<button v-if="unseenCount" @click.prevent="markAsSeen" class="read-button">{{$t('notifications.read')}}</button> <button
v-if="unseenCount"
class="read-button"
@click.prevent="markAsSeen"
>
{{ $t('notifications.read') }}
</button>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div v-for="notification in visibleNotifications" :key="notification.id" class="notification" :class='{"unseen": !minimalMode && !notification.seen}'> <div
<div class="notification-overlay"></div> v-for="notification in visibleNotifications"
<notification :notification="notification"></notification> :key="notification.id"
class="notification"
:class="{&quot;unseen&quot;: !minimalMode && !notification.seen}"
>
<div class="notification-overlay" />
<notification :notification="notification" />
</div> </div>
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<div v-if="bottomedOut" class="new-status-notification text-center panel-footer faint"> <div
{{$t('notifications.no_more_notifications')}} v-if="bottomedOut"
class="new-status-notification text-center panel-footer faint"
>
{{ $t('notifications.no_more_notifications') }}
</div> </div>
<a v-else-if="!loading" href="#" v-on:click.prevent="fetchOlderNotifications()"> <a
v-else-if="!loading"
href="#"
@click.prevent="fetchOlderNotifications()"
>
<div class="new-status-notification text-center panel-footer"> <div class="new-status-notification text-center panel-footer">
{{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older')}} {{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }}
</div> </div>
</a> </a>
<div v-else class="new-status-notification text-center panel-footer"> <div
<i class="icon-spin3 animate-spin"/> v-else
class="new-status-notification text-center panel-footer"
>
<i class="icon-spin3 animate-spin" />
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,27 +1,39 @@
<template> <template>
<div class="opacity-control style-control" :class="{ disabled: !present || disabled }"> <div
<label :for="name" class="label"> class="opacity-control style-control"
{{$t('settings.style.common.opacity')}} :class="{ disabled: !present || disabled }"
</label> >
<input <label
v-if="typeof fallback !== 'undefined'" :for="name"
class="opt exclude-disabled" class="label"
:id="name + '-o'" >
type="checkbox" {{ $t('settings.style.common.opacity') }}
:checked="present" </label>
@input="$emit('input', !present ? fallback : undefined)"> <input
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label> v-if="typeof fallback !== 'undefined'"
<input :id="name + '-o'"
:id="name" class="opt exclude-disabled"
class="input-number" type="checkbox"
type="number" :checked="present"
:value="value || fallback" @input="$emit('input', !present ? fallback : undefined)"
:disabled="!present || disabled" >
@input="$emit('input', $event.target.value)" <label
max="1" v-if="typeof fallback !== 'undefined'"
min="0" class="opt-l"
step=".05"> :for="name + '-o'"
</div> />
<input
:id="name"
class="input-number"
type="number"
:value="value || fallback"
:disabled="!present || disabled"
max="1"
min="0"
step=".05"
@input="$emit('input', $event.target.value)"
>
</div>
</template> </template>
<script> <script>

View file

@ -1,24 +1,33 @@
<template> <template>
<div class="poll" v-bind:class="containerClass"> <div
class="poll"
:class="containerClass"
>
<div <div
class="poll-option"
v-for="(option, index) in options" v-for="(option, index) in options"
:key="index" :key="index"
class="poll-option"
> >
<div v-if="showResults" :title="resultTitle(option)" class="option-result"> <div
v-if="showResults"
:title="resultTitle(option)"
class="option-result"
>
<div class="option-result-label"> <div class="option-result-label">
<span class="result-percentage"> <span class="result-percentage">
{{percentageForOption(option.votes_count)}}% {{ percentageForOption(option.votes_count) }}%
</span> </span>
<span>{{option.title}}</span> <span>{{ option.title }}</span>
</div> </div>
<div <div
class="result-fill" class="result-fill"
:style="{ 'width': `${percentageForOption(option.votes_count)}%` }" :style="{ 'width': `${percentageForOption(option.votes_count)}%` }"
> />
</div>
</div> </div>
<div v-else @click="activateOption(index)"> <div
v-else
@click="activateOption(index)"
>
<input <input
v-if="poll.multiple" v-if="poll.multiple"
type="checkbox" type="checkbox"
@ -32,7 +41,7 @@
:value="index" :value="index"
> >
<label class="option-vote"> <label class="option-vote">
<div>{{option.title}}</div> <div>{{ option.title }}</div>
</label> </label>
</div> </div>
</div> </div>
@ -41,16 +50,20 @@
v-if="!showResults" v-if="!showResults"
class="btn btn-default poll-vote-button" class="btn btn-default poll-vote-button"
type="button" type="button"
@click="vote"
:disabled="isDisabled" :disabled="isDisabled"
@click="vote"
> >
{{$t('polls.vote')}} {{ $t('polls.vote') }}
</button> </button>
<div class="total"> <div class="total">
{{totalVotesCount}} {{ $t("polls.votes") }}&nbsp;·&nbsp; {{ totalVotesCount }} {{ $t("polls.votes") }}&nbsp;·&nbsp;
</div> </div>
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'"> <i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
<Timeago :time="this.expiresAt" :auto-update="60" :now-threshold="0" /> <Timeago
:time="this.expiresAt"
:auto-update="60"
:now-threshold="0"
/>
</i18n> </i18n>
</div> </div>
</div> </div>

View file

@ -1,20 +1,33 @@
<template> <template>
<div class="poll-form" v-if="visible"> <div
<div class="poll-option" v-for="(option, index) in options" :key="index"> v-if="visible"
class="poll-form"
>
<div
v-for="(option, index) in options"
:key="index"
class="poll-option"
>
<div class="input-container"> <div class="input-container">
<input <input
:id="`poll-${index}`"
v-model="options[index]"
class="poll-option-input" class="poll-option-input"
type="text" type="text"
:placeholder="$t('polls.option')" :placeholder="$t('polls.option')"
:maxlength="maxLength" :maxlength="maxLength"
:id="`poll-${index}`"
v-model="options[index]"
@change="updatePollToParent" @change="updatePollToParent"
@keydown.enter.stop.prevent="nextOption(index)" @keydown.enter.stop.prevent="nextOption(index)"
> >
</div> </div>
<div class="icon-container" v-if="options.length > 2"> <div
<i class="icon-cancel" @click="deleteOption(index)"></i> v-if="options.length > 2"
class="icon-container"
>
<i
class="icon-cancel"
@click="deleteOption(index)"
/>
</div> </div>
</div> </div>
<a <a
@ -26,34 +39,50 @@
{{ $t("polls.add_option") }} {{ $t("polls.add_option") }}
</a> </a>
<div class="poll-type-expiry"> <div class="poll-type-expiry">
<div class="poll-type" :title="$t('polls.type')"> <div
<label for="poll-type-selector" class="select"> class="poll-type"
<select class="select" v-model="pollType" @change="updatePollToParent"> :title="$t('polls.type')"
<option value="single">{{$t('polls.single_choice')}}</option> >
<option value="multiple">{{$t('polls.multiple_choices')}}</option> <label
for="poll-type-selector"
class="select"
>
<select
v-model="pollType"
class="select"
@change="updatePollToParent"
>
<option value="single">{{ $t('polls.single_choice') }}</option>
<option value="multiple">{{ $t('polls.multiple_choices') }}</option>
</select> </select>
<i class="icon-down-open"/> <i class="icon-down-open" />
</label> </label>
</div> </div>
<div class="poll-expiry" :title="$t('polls.expiry')"> <div
<input class="poll-expiry"
:title="$t('polls.expiry')"
>
<input
v-model="expiryAmount"
type="number" type="number"
class="expiry-amount hide-number-spinner" class="expiry-amount hide-number-spinner"
:min="minExpirationInCurrentUnit" :min="minExpirationInCurrentUnit"
:max="maxExpirationInCurrentUnit" :max="maxExpirationInCurrentUnit"
v-model="expiryAmount"
@change="expiryAmountChange" @change="expiryAmountChange"
> >
<label class="expiry-unit select"> <label class="expiry-unit select">
<select <select
v-model="expiryUnit" v-model="expiryUnit"
@change="expiryAmountChange" @change="expiryAmountChange"
> >
<option v-for="unit in expiryUnits" :value="unit"> <option
v-for="unit in expiryUnits"
:value="unit"
>
{{ $t(`time.${unit}_short`, ['']) }} {{ $t(`time.${unit}_short`, ['']) }}
</option> </option>
</select> </select>
<i class="icon-down-open"/> <i class="icon-down-open" />
</label> </label>
</div> </div>
</div> </div>

View file

@ -1,147 +1,253 @@
<template> <template>
<div class="post-status-form"> <div class="post-status-form">
<form @submit.prevent="postStatus(newStatus)" autocomplete="off"> <form
<div class="form-group" > autocomplete="off"
<i18n @submit.prevent="postStatus(newStatus)"
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'" >
path="post_status.account_not_locked_warning" <div class="form-group">
tag="p" <i18n
class="visibility-notice"> v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
<router-link :to="{ name: 'user-settings' }">{{ $t('post_status.account_not_locked_warning_link') }}</router-link> path="post_status.account_not_locked_warning"
</i18n> tag="p"
<p v-if="!hideScopeNotice && newStatus.visibility === 'public'" class="visibility-notice notice-dismissible"> class="visibility-notice"
<span>{{ $t('post_status.scope_notice.public') }}</span>
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
<i class='icon-cancel'></i>
</a>
</p>
<p v-else-if="!hideScopeNotice && newStatus.visibility === 'unlisted'" class="visibility-notice notice-dismissible">
<span>{{ $t('post_status.scope_notice.unlisted') }}</span>
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
<i class='icon-cancel'></i>
</a>
</p>
<p v-else-if="!hideScopeNotice && newStatus.visibility === 'private' && $store.state.users.currentUser.locked" class="visibility-notice notice-dismissible">
<span>{{ $t('post_status.scope_notice.private') }}</span>
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
<i class='icon-cancel'></i>
</a>
</p>
<p v-else-if="newStatus.visibility === 'direct'" class="visibility-notice">
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
</p>
<EmojiInput
v-if="newStatus.spoilerText || alwaysShowSubject"
:suggest="emojiSuggestor"
v-model="newStatus.spoilerText"
class="form-control"
> >
<input <router-link :to="{ name: 'user-settings' }">
{{ $t('post_status.account_not_locked_warning_link') }}
type="text" </router-link>
:placeholder="$t('post_status.content_warning')" </i18n>
v-model="newStatus.spoilerText"
class="form-post-subject"
/>
</EmojiInput>
<EmojiInput
:suggest="emojiUserSuggestor"
v-model="newStatus.status"
class="form-control main-input"
>
<textarea
ref="textarea"
v-model="newStatus.status"
:placeholder="$t('post_status.default')"
rows="1"
@keydown.meta.enter="postStatus(newStatus)"
@keyup.ctrl.enter="postStatus(newStatus)"
@drop="fileDrop"
@dragover.prevent="fileDrag"
@input="resize"
@paste="paste"
:disabled="posting"
class="form-post-body"
>
</textarea>
<p <p
v-if="hasStatusLengthLimit" v-if="!hideScopeNotice && newStatus.visibility === 'public'"
class="character-counter faint" class="visibility-notice notice-dismissible"
:class="{ error: isOverLengthLimit }"
> >
{{ charactersLeft }} <span>{{ $t('post_status.scope_notice.public') }}</span>
<a
class="button-icon dismiss"
@click.prevent="dismissScopeNotice()"
>
<i class="icon-cancel" />
</a>
</p> </p>
</EmojiInput> <p
<div class="visibility-tray"> v-else-if="!hideScopeNotice && newStatus.visibility === 'unlisted'"
<div class="text-format" v-if="postFormats.length > 1"> class="visibility-notice notice-dismissible"
<label for="post-content-type" class="select"> >
<select id="post-content-type" v-model="newStatus.contentType" class="form-control"> <span>{{ $t('post_status.scope_notice.unlisted') }}</span>
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat"> <a
{{$t(`post_status.content_type["${postFormat}"]`)}} class="button-icon dismiss"
</option> @click.prevent="dismissScopeNotice()"
</select> >
<i class="icon-down-open"></i> <i class="icon-cancel" />
</label> </a>
</div> </p>
<div class="text-format" v-if="postFormats.length === 1"> <p
<span class="only-format"> v-else-if="!hideScopeNotice && newStatus.visibility === 'private' && $store.state.users.currentUser.locked"
{{$t(`post_status.content_type["${postFormats[0]}"]`)}} class="visibility-notice notice-dismissible"
</span> >
</div> <span>{{ $t('post_status.scope_notice.private') }}</span>
<a
class="button-icon dismiss"
@click.prevent="dismissScopeNotice()"
>
<i class="icon-cancel" />
</a>
</p>
<p
v-else-if="newStatus.visibility === 'direct'"
class="visibility-notice"
>
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
</p>
<EmojiInput
v-if="newStatus.spoilerText || alwaysShowSubject"
v-model="newStatus.spoilerText"
:suggest="emojiSuggestor"
class="form-control"
>
<input
<scope-selector v-model="newStatus.spoilerText"
:showAll="showAllScopes" type="text"
:userDefault="userDefaultScope" :placeholder="$t('post_status.content_warning')"
:originalScope="copyMessageScope" class="form-post-subject"
:initialScope="newStatus.visibility" >
:onScopeChange="changeVis"/> </EmojiInput>
</div> <EmojiInput
</div> v-model="newStatus.status"
<poll-form :suggest="emojiUserSuggestor"
ref="pollForm" class="form-control main-input"
v-if="pollsAvailable" >
:visible="pollFormVisible" <textarea
@update-poll="setPoll" ref="textarea"
/> v-model="newStatus.status"
<div class='form-bottom'> :placeholder="$t('post_status.default')"
<div class='form-bottom-left'> rows="1"
<media-upload ref="mediaUpload" @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload> :disabled="posting"
<div v-if="pollsAvailable" class="poll-icon"> class="form-post-body"
<i @keydown.meta.enter="postStatus(newStatus)"
:title="$t('polls.add_poll')" @keyup.ctrl.enter="postStatus(newStatus)"
@click="togglePollForm" @drop="fileDrop"
class="icon-chart-bar btn btn-default" @dragover.prevent="fileDrag"
:class="pollFormVisible && 'selected'" @input="resize"
@paste="paste"
/>
<p
v-if="hasStatusLengthLimit"
class="character-counter faint"
:class="{ error: isOverLengthLimit }"
>
{{ charactersLeft }}
</p>
</EmojiInput>
<div class="visibility-tray">
<div
v-if="postFormats.length > 1"
class="text-format"
>
<label
for="post-content-type"
class="select"
>
<select
id="post-content-type"
v-model="newStatus.contentType"
class="form-control"
>
<option
v-for="postFormat in postFormats"
:key="postFormat"
:value="postFormat"
>
{{ $t(`post_status.content_type["${postFormat}"]`) }}
</option>
</select>
<i class="icon-down-open" />
</label>
</div>
<div
v-if="postFormats.length === 1"
class="text-format"
>
<span class="only-format">
{{ $t(`post_status.content_type["${postFormats[0]}"]`) }}
</span>
</div>
<scope-selector
:show-all="showAllScopes"
:user-default="userDefaultScope"
:original-scope="copyMessageScope"
:initial-scope="newStatus.visibility"
:on-scope-change="changeVis"
/> />
</div> </div>
</div> </div>
<poll-form
v-if="pollsAvailable"
ref="pollForm"
:visible="pollFormVisible"
@update-poll="setPoll"
/>
<div class="form-bottom">
<div class="form-bottom-left">
<media-upload
ref="mediaUpload"
:drop-files="dropFiles"
@uploading="disableSubmit"
@uploaded="addMediaFile"
@upload-failed="uploadFailed"
/>
<div
v-if="pollsAvailable"
class="poll-icon"
>
<i
:title="$t('polls.add_poll')"
class="icon-chart-bar btn btn-default"
:class="pollFormVisible && 'selected'"
@click="togglePollForm"
/>
</div>
</div>
<button v-if="posting" disabled class="btn btn-default">{{$t('post_status.posting')}}</button> <button
<button v-else-if="isOverLengthLimit" disabled class="btn btn-default">{{$t('general.submit')}}</button> v-if="posting"
<button v-else :disabled="submitDisabled" type="submit" class="btn btn-default">{{$t('general.submit')}}</button> disabled
</div> class="btn btn-default"
<div class='alert error' v-if="error"> >
Error: {{ error }} {{ $t('post_status.posting') }}
<i class="button-icon icon-cancel" @click="clearError"></i> </button>
</div> <button
<div class="attachments"> v-else-if="isOverLengthLimit"
<div class="media-upload-wrapper" v-for="file in newStatus.files"> disabled
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i> class="btn btn-default"
<div class="media-upload-container attachment"> >
<img class="thumbnail media-upload" :src="file.url" v-if="type(file) === 'image'"></img> {{ $t('general.submit') }}
<video v-if="type(file) === 'video'" :src="file.url" controls></video> </button>
<audio v-if="type(file) === 'audio'" :src="file.url" controls></audio> <button
<a v-if="type(file) === 'unknown'" :href="file.url">{{file.url}}</a> v-else
:disabled="submitDisabled"
type="submit"
class="btn btn-default"
>
{{ $t('general.submit') }}
</button>
</div>
<div
v-if="error"
class="alert error"
>
Error: {{ error }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div>
<div class="attachments">
<div
v-for="file in newStatus.files"
class="media-upload-wrapper"
>
<i
class="fa button-icon icon-cancel"
@click="removeMediaFile(file)"
/>
<div class="media-upload-container attachment">
<img
v-if="type(file) === 'image'"
class="thumbnail media-upload"
:src="file.url"
></img>
<video
v-if="type(file) === 'video'"
:src="file.url"
controls
/>
<audio
v-if="type(file) === 'audio'"
:src="file.url"
controls
/>
<a
v-if="type(file) === 'unknown'"
:href="file.url"
>{{ file.url }}</a>
</div>
</div> </div>
</div> </div>
</div> <div
<div class="upload_settings" v-if="newStatus.files.length > 0"> v-if="newStatus.files.length > 0"
<input type="checkbox" id="filesSensitive" v-model="newStatus.nsfw"> class="upload_settings"
<label for="filesSensitive">{{$t('post_status.attachments_sensitive')}}</label> >
</div> <input
</form> id="filesSensitive"
</div> v-model="newStatus.nsfw"
type="checkbox"
>
<label for="filesSensitive">{{ $t('post_status.attachments_sensitive') }}</label>
</div>
</form>
</div>
</template> </template>
<script src="./post_status_form.js"></script> <script src="./post_status_form.js"></script>
@ -217,7 +323,6 @@
.icon-chart-bar { .icon-chart-bar {
cursor: pointer; cursor: pointer;
} }
.error { .error {
text-align: center; text-align: center;

View file

@ -1,5 +1,8 @@
<template> <template>
<button :disabled="progress || disabled" @click="onClick"> <button
:disabled="progress || disabled"
@click="onClick"
>
<template v-if="progress"> <template v-if="progress">
<slot name="progress" /> <slot name="progress" />
</template> </template>

View file

@ -1,5 +1,9 @@
<template> <template>
<Timeline :title="$t('nav.twkn')" v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/> <Timeline
:title="$t('nav.twkn')"
:timeline="timeline"
:timeline-name="'publicAndExternal'"
/>
</template> </template>
<script src="./public_and_external_timeline.js"></script> <script src="./public_and_external_timeline.js"></script>

View file

@ -1,5 +1,9 @@
<template> <template>
<Timeline :title="$t('nav.public_tl')" v-bind:timeline="timeline" v-bind:timeline-name="'public'"/> <Timeline
:title="$t('nav.public_tl')"
:timeline="timeline"
:timeline-name="'public'"
/>
</template> </template>
<script src="./public_timeline.js"></script> <script src="./public_timeline.js"></script>

View file

@ -1,37 +1,50 @@
<template> <template>
<div class="range-control style-control" :class="{ disabled: !present || disabled }"> <div
<label :for="name" class="label"> class="range-control style-control"
{{label}} :class="{ disabled: !present || disabled }"
</label> >
<input <label
v-if="typeof fallback !== 'undefined'" :for="name"
class="opt exclude-disabled" class="label"
:id="name + '-o'" >
type="checkbox" {{ label }}
:checked="present" </label>
@input="$emit('input', !present ? fallback : undefined)"> <input
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label> v-if="typeof fallback !== 'undefined'"
<input :id="name + '-o'"
:id="name" class="opt exclude-disabled"
class="input-number" type="checkbox"
type="range" :checked="present"
:value="value || fallback" @input="$emit('input', !present ? fallback : undefined)"
:disabled="!present || disabled" >
@input="$emit('input', $event.target.value)" <label
:max="max || hardMax || 100" v-if="typeof fallback !== 'undefined'"
:min="min || hardMin || 0" class="opt-l"
:step="step || 1"> :for="name + '-o'"
<input />
:id="name" <input
class="input-number" :id="name"
type="number" class="input-number"
:value="value || fallback" type="range"
:disabled="!present || disabled" :value="value || fallback"
@input="$emit('input', $event.target.value)" :disabled="!present || disabled"
:max="hardMax" :max="max || hardMax || 100"
:min="hardMin" :min="min || hardMin || 0"
:step="step || 1"> :step="step || 1"
</div> @input="$emit('input', $event.target.value)"
>
<input
:id="name"
class="input-number"
type="number"
:value="value || fallback"
:disabled="!present || disabled"
:max="hardMax"
:min="hardMin"
:step="step || 1"
@input="$emit('input', $event.target.value)"
>
</div>
</template> </template>
<script> <script>

View file

@ -1,109 +1,231 @@
<template> <template>
<div class="settings panel panel-default"> <div class="settings panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{$t('registration.registration')}} {{ $t('registration.registration') }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form v-on:submit.prevent='submit(user)' class='registration-form'> <form
<div class='container'> class="registration-form"
<div class='text-fields'> @submit.prevent="submit(user)"
<div class='form-group' :class="{ 'form-group--error': $v.user.username.$error }"> >
<label class='form--label' for='sign-up-username'>{{$t('login.username')}}</label> <div class="container">
<input :disabled="isPending" v-model.trim='$v.user.username.$model' class='form-control' id='sign-up-username' :placeholder="$t('registration.username_placeholder')"> <div class="text-fields">
<div
class="form-group"
:class="{ 'form-group--error': $v.user.username.$error }"
>
<label
class="form--label"
for="sign-up-username"
>{{ $t('login.username') }}</label>
<input
id="sign-up-username"
v-model.trim="$v.user.username.$model"
:disabled="isPending"
class="form-control"
:placeholder="$t('registration.username_placeholder')"
>
</div> </div>
<div class="form-error" v-if="$v.user.username.$dirty"> <div
v-if="$v.user.username.$dirty"
class="form-error"
>
<ul> <ul>
<li v-if="!$v.user.username.required"> <li v-if="!$v.user.username.required">
<span>{{$t('registration.validations.username_required')}}</span> <span>{{ $t('registration.validations.username_required') }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class='form-group' :class="{ 'form-group--error': $v.user.fullname.$error }"> <div
<label class='form--label' for='sign-up-fullname'>{{$t('registration.fullname')}}</label> class="form-group"
<input :disabled="isPending" v-model.trim='$v.user.fullname.$model' class='form-control' id='sign-up-fullname' :placeholder="$t('registration.fullname_placeholder')"> :class="{ 'form-group--error': $v.user.fullname.$error }"
>
<label
class="form--label"
for="sign-up-fullname"
>{{ $t('registration.fullname') }}</label>
<input
id="sign-up-fullname"
v-model.trim="$v.user.fullname.$model"
:disabled="isPending"
class="form-control"
:placeholder="$t('registration.fullname_placeholder')"
>
</div> </div>
<div class="form-error" v-if="$v.user.fullname.$dirty"> <div
v-if="$v.user.fullname.$dirty"
class="form-error"
>
<ul> <ul>
<li v-if="!$v.user.fullname.required"> <li v-if="!$v.user.fullname.required">
<span>{{$t('registration.validations.fullname_required')}}</span> <span>{{ $t('registration.validations.fullname_required') }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class='form-group' :class="{ 'form-group--error': $v.user.email.$error }"> <div
<label class='form--label' for='email'>{{$t('registration.email')}}</label> class="form-group"
<input :disabled="isPending" v-model='$v.user.email.$model' class='form-control' id='email' type="email"> :class="{ 'form-group--error': $v.user.email.$error }"
>
<label
class="form--label"
for="email"
>{{ $t('registration.email') }}</label>
<input
id="email"
v-model="$v.user.email.$model"
:disabled="isPending"
class="form-control"
type="email"
>
</div> </div>
<div class="form-error" v-if="$v.user.email.$dirty"> <div
v-if="$v.user.email.$dirty"
class="form-error"
>
<ul> <ul>
<li v-if="!$v.user.email.required"> <li v-if="!$v.user.email.required">
<span>{{$t('registration.validations.email_required')}}</span> <span>{{ $t('registration.validations.email_required') }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class='form-group'> <div class="form-group">
<label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label> <label
<textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="bioPlaceholder"></textarea> class="form--label"
for="bio"
>{{ $t('registration.bio') }} ({{ $t('general.optional') }})</label>
<textarea
id="bio"
v-model="user.bio"
:disabled="isPending"
class="form-control"
:placeholder="bioPlaceholder"
/>
</div> </div>
<div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }"> <div
<label class='form--label' for='sign-up-password'>{{$t('login.password')}}</label> class="form-group"
<input :disabled="isPending" v-model='user.password' class='form-control' id='sign-up-password' type='password'> :class="{ 'form-group--error': $v.user.password.$error }"
>
<label
class="form--label"
for="sign-up-password"
>{{ $t('login.password') }}</label>
<input
id="sign-up-password"
v-model="user.password"
:disabled="isPending"
class="form-control"
type="password"
>
</div> </div>
<div class="form-error" v-if="$v.user.password.$dirty"> <div
v-if="$v.user.password.$dirty"
class="form-error"
>
<ul> <ul>
<li v-if="!$v.user.password.required"> <li v-if="!$v.user.password.required">
<span>{{$t('registration.validations.password_required')}}</span> <span>{{ $t('registration.validations.password_required') }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class='form-group' :class="{ 'form-group--error': $v.user.confirm.$error }"> <div
<label class='form--label' for='sign-up-password-confirmation'>{{$t('registration.password_confirm')}}</label> class="form-group"
<input :disabled="isPending" v-model='user.confirm' class='form-control' id='sign-up-password-confirmation' type='password'> :class="{ 'form-group--error': $v.user.confirm.$error }"
>
<label
class="form--label"
for="sign-up-password-confirmation"
>{{ $t('registration.password_confirm') }}</label>
<input
id="sign-up-password-confirmation"
v-model="user.confirm"
:disabled="isPending"
class="form-control"
type="password"
>
</div> </div>
<div class="form-error" v-if="$v.user.confirm.$dirty"> <div
v-if="$v.user.confirm.$dirty"
class="form-error"
>
<ul> <ul>
<li v-if="!$v.user.confirm.required"> <li v-if="!$v.user.confirm.required">
<span>{{$t('registration.validations.password_confirmation_required')}}</span> <span>{{ $t('registration.validations.password_confirmation_required') }}</span>
</li> </li>
<li v-if="!$v.user.confirm.sameAsPassword"> <li v-if="!$v.user.confirm.sameAsPassword">
<span>{{$t('registration.validations.password_confirmation_match')}}</span> <span>{{ $t('registration.validations.password_confirmation_match') }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class="form-group" id="captcha-group" v-if="captcha.type != 'none'"> <div
<label class='form--label' for='captcha-label'>{{$t('captcha')}}</label> v-if="captcha.type != 'none'"
id="captcha-group"
class="form-group"
>
<label
class="form--label"
for="captcha-label"
>{{ $t('captcha') }}</label>
<template v-if="captcha.type == 'kocaptcha'"> <template v-if="captcha.type == 'kocaptcha'">
<img v-bind:src="captcha.url" v-on:click="setCaptcha"> <img
:src="captcha.url"
@click="setCaptcha"
>
<sub>{{$t('registration.new_captcha')}}</sub> <sub>{{ $t('registration.new_captcha') }}</sub>
<input :disabled="isPending" <input
v-model='captcha.solution' id="captcha-answer"
class='form-control' id='captcha-answer' type='text' autocomplete="off"> v-model="captcha.solution"
:disabled="isPending"
class="form-control"
type="text"
autocomplete="off"
>
</template> </template>
</div> </div>
<div class='form-group' v-if='token' > <div
<label for='token'>{{$t('registration.token')}}</label> v-if="token"
<input disabled='true' v-model='token' class='form-control' id='token' type='text'> class="form-group"
>
<label for="token">{{ $t('registration.token') }}</label>
<input
id="token"
v-model="token"
disabled="true"
class="form-control"
type="text"
>
</div> </div>
<div class='form-group'> <div class="form-group">
<button :disabled="isPending" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button> <button
:disabled="isPending"
type="submit"
class="btn btn-default"
>
{{ $t('general.submit') }}
</button>
</div> </div>
</div> </div>
<div class='terms-of-service' v-html="termsOfService"> <div
</div> class="terms-of-service"
v-html="termsOfService"
/>
</div> </div>
<div v-if="serverValidationErrors.length" class='form-group'> <div
<div class='alert error'> v-if="serverValidationErrors.length"
<span v-for="error in serverValidationErrors">{{error}}</span> class="form-group"
>
<div class="alert error">
<span v-for="error in serverValidationErrors">{{ error }}</span>
</div> </div>
</div> </div>
</form> </form>

View file

@ -1,9 +1,23 @@
<template> <template>
<div class="remote-follow"> <div class="remote-follow">
<form method="POST" :action='subscribeUrl'> <form
<input type="hidden" name="nickname" :value="user.screen_name"> method="POST"
<input type="hidden" name="profile" value=""> :action="subscribeUrl"
<button click="submit" class="remote-button"> >
<input
type="hidden"
name="nickname"
:value="user.screen_name"
>
<input
type="hidden"
name="profile"
value=""
>
<button
click="submit"
class="remote-button"
>
{{ $t('user_card.remote_follow') }} {{ $t('user_card.remote_follow') }}
</button> </button>
</form> </form>

View file

@ -1,16 +1,29 @@
<template> <template>
<div v-if="loggedIn"> <div v-if="loggedIn">
<template v-if="visibility !== 'private' && visibility !== 'direct'"> <template v-if="visibility !== 'private' && visibility !== 'direct'">
<i :class='classes' class='button-icon retweet-button icon-retweet rt-active' v-on:click.prevent='retweet()' :title="$t('tool_tip.repeat')"></i> <i
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span> :class="classes"
class="button-icon retweet-button icon-retweet rt-active"
:title="$t('tool_tip.repeat')"
@click.prevent="retweet()"
/>
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
</template> </template>
<template v-else> <template v-else>
<i :class='classes' class='button-icon icon-lock' :title="$t('timeline.no_retweet_hint')"></i> <i
:class="classes"
class="button-icon icon-lock"
:title="$t('timeline.no_retweet_hint')"
/>
</template> </template>
</div> </div>
<div v-else-if="!loggedIn"> <div v-else-if="!loggedIn">
<i :class='classes' class='button-icon icon-retweet' :title="$t('tool_tip.repeat')"></i> <i
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span> :class="classes"
class="button-icon icon-retweet"
:title="$t('tool_tip.repeat')"
/>
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
</div> </div>
</template> </template>

View file

@ -1,30 +1,37 @@
<template> <template>
<div v-if="!showNothing" class="scope-selector"> <div
<i class="icon-mail-alt" v-if="!showNothing"
:class="css.direct" class="scope-selector"
:title="$t('post_status.scope.direct')" >
v-if="showDirect" <i
@click="changeVis('direct')"> v-if="showDirect"
</i> class="icon-mail-alt"
<i class="icon-lock" :class="css.direct"
:class="css.private" :title="$t('post_status.scope.direct')"
:title="$t('post_status.scope.private')" @click="changeVis('direct')"
v-if="showPrivate" />
v-on:click="changeVis('private')"> <i
</i> v-if="showPrivate"
<i class="icon-lock-open-alt" class="icon-lock"
:class="css.unlisted" :class="css.private"
:title="$t('post_status.scope.unlisted')" :title="$t('post_status.scope.private')"
v-if="showUnlisted" @click="changeVis('private')"
@click="changeVis('unlisted')"> />
</i> <i
<i class="icon-globe" v-if="showUnlisted"
:class="css.public" class="icon-lock-open-alt"
:title="$t('post_status.scope.public')" :class="css.unlisted"
v-if="showPublic" :title="$t('post_status.scope.unlisted')"
@click="changeVis('public')"> @click="changeVis('unlisted')"
</i> />
</div> <i
v-if="showPublic"
class="icon-globe"
:class="css.public"
:title="$t('post_status.scope.public')"
@click="changeVis('public')"
/>
</div>
</template> </template>
<script src="./scope_selector.js"></script> <script src="./scope_selector.js"></script>

View file

@ -1,23 +1,52 @@
<template> <template>
<div class="selectable-list"> <div class="selectable-list">
<div class="selectable-list-header" v-if="items.length > 0"> <div
v-if="items.length > 0"
class="selectable-list-header"
>
<div class="selectable-list-checkbox-wrapper"> <div class="selectable-list-checkbox-wrapper">
<Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox> <Checkbox
:checked="allSelected"
:indeterminate="someSelected"
@change="toggleAll"
>
{{ $t('selectable_list.select_all') }}
</Checkbox>
</div> </div>
<div class="selectable-list-header-actions"> <div class="selectable-list-header-actions">
<slot name="header" :selected="filteredSelected" /> <slot
name="header"
:selected="filteredSelected"
/>
</div> </div>
</div> </div>
<List :items="items" :getKey="getKey"> <List
<template slot="item" slot-scope="{item}"> :items="items"
<div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }"> :get-key="getKey"
>
<template
slot="item"
slot-scope="{item}"
>
<div
class="selectable-list-item-inner"
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
>
<div class="selectable-list-checkbox-wrapper"> <div class="selectable-list-checkbox-wrapper">
<Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" /> <Checkbox
:checked="isSelected(item)"
@change="checked => toggle(checked, item)"
/>
</div> </div>
<slot name="item" :item="item" /> <slot
name="item"
:item="item"
/>
</div> </div>
</template> </template>
<template slot="empty"><slot name="empty" /></template> <template slot="empty">
<slot name="empty" />
</template>
</List> </List>
</div> </div>
</template> </template>

View file

@ -1,305 +1,483 @@
<template> <template>
<div class="settings panel panel-default"> <div class="settings panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<div class="title"> <div class="title">
{{$t('settings.settings')}} {{ $t('settings.settings') }}
</div>
<transition name="fade">
<template v-if="currentSaveStateNotice">
<div
v-if="currentSaveStateNotice.error"
class="alert error"
@click.prevent
>
{{ $t('settings.saving_err') }}
</div>
<div
v-if="!currentSaveStateNotice.error"
class="alert transparent"
@click.prevent
>
{{ $t('settings.saving_ok') }}
</div>
</template>
</transition>
</div> </div>
<div class="panel-body">
<transition name="fade"> <keep-alive>
<template v-if="currentSaveStateNotice"> <tab-switcher>
<div @click.prevent class="alert error" v-if="currentSaveStateNotice.error"> <div :label="$t('settings.general')">
{{ $t('settings.saving_err') }} <div class="setting-item">
</div> <h2>{{ $t('settings.interface') }}</h2>
<ul class="setting-list">
<div @click.prevent class="alert transparent" v-if="!currentSaveStateNotice.error">
{{ $t('settings.saving_ok') }}
</div>
</template>
</transition>
</div>
<div class="panel-body">
<keep-alive>
<tab-switcher>
<div :label="$t('settings.general')" >
<div class="setting-item">
<h2>{{ $t('settings.interface') }}</h2>
<ul class="setting-list">
<li>
<interface-language-switcher />
</li>
<li v-if="instanceSpecificPanelPresent">
<input type="checkbox" id="hideISP" v-model="hideISPLocal">
<label for="hideISP">{{$t('settings.hide_isp')}}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{$t('nav.timeline')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="hideMutedPosts" v-model="hideMutedPostsLocal">
<label for="hideMutedPosts">{{$t('settings.hide_muted_posts')}} {{$t('settings.instance_default', { value: hideMutedPostsDefault })}}</label>
</li>
<li>
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}</label>
</li>
<li>
<input type="checkbox" id="streaming" v-model="streamingLocal">
<label for="streaming">{{$t('settings.streaming')}}</label>
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
<li> <li>
<input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal"> <interface-language-switcher />
<label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label> </li>
<li v-if="instanceSpecificPanelPresent">
<input
id="hideISP"
v-model="hideISPLocal"
type="checkbox"
>
<label for="hideISP">{{ $t('settings.hide_isp') }}</label>
</li> </li>
</ul> </ul>
</li> </div>
<li> <div class="setting-item">
<input type="checkbox" id="autoload" v-model="autoLoadLocal"> <h2>{{ $t('nav.timeline') }}</h2>
<label for="autoload">{{$t('settings.autoload')}}</label> <ul class="setting-list">
</li>
<li>
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{$t('settings.composing')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="scopeCopy" v-model="scopeCopyLocal">
<label for="scopeCopy">
{{$t('settings.scope_copy')}} {{$t('settings.instance_default', { value: scopeCopyDefault })}}
</label>
</li>
<li>
<input type="checkbox" id="subjectHide" v-model="alwaysShowSubjectInputLocal">
<label for="subjectHide">
{{$t('settings.subject_input_always_show')}} {{$t('settings.instance_default', { value: alwaysShowSubjectInputDefault })}}
</label>
</li>
<li>
<div>
{{$t('settings.subject_line_behavior')}}
<label for="subjectLineBehavior" class="select">
<select id="subjectLineBehavior" v-model="subjectLineBehaviorLocal">
<option value="email">
{{$t('settings.subject_line_email')}}
{{subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : ''}}
</option>
<option value="masto">
{{$t('settings.subject_line_mastodon')}}
{{subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : ''}}
</option>
<option value="noop">
{{$t('settings.subject_line_noop')}}
{{subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : ''}}
</option>
</select>
<i class="icon-down-open"/>
</label>
</div>
</li>
<li v-if="postFormats.length > 0">
<div>
{{$t('settings.post_status_content_type')}}
<label for="postContentType" class="select">
<select id="postContentType" v-model="postContentTypeLocal">
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat">
{{$t(`post_status.content_type["${postFormat}"]`)}}
{{postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : ''}}
</option>
</select>
<i class="icon-down-open"/>
</label>
</div>
</li>
<li>
<input type="checkbox" id="minimalScopesMode" v-model="minimalScopesModeLocal">
<label for="minimalScopesMode">
{{$t('settings.minimal_scopes_mode')}} {{$t('settings.instance_default', { value: minimalScopesModeDefault })}}
</label>
</li>
<li>
<input type="checkbox" id="autohideFloatingPostButton" v-model="autohideFloatingPostButtonLocal">
<label for="autohideFloatingPostButton">{{$t('settings.autohide_floating_post_button')}}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{$t('settings.attachments')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal">
<label for="hideAttachments">{{$t('settings.hide_attachments_in_tl')}}</label>
</li>
<li>
<input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
<label for="hideAttachmentsInConv">{{$t('settings.hide_attachments_in_convo')}}</label>
</li>
<li>
<label for="maxThumbnails">{{$t('settings.max_thumbnails')}}</label>
<input class="number-input" type="number" id="maxThumbnails" v-model.number="maxThumbnails" min="0" step="1">
</li>
<li>
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
</li>
<ul class="setting-list suboptions" >
<li>
<input :disabled="!hideNsfwLocal" type="checkbox" id="preloadImage" v-model="preloadImage">
<label for="preloadImage">{{$t('settings.preload_images')}}</label>
</li>
<li>
<input :disabled="!hideNsfwLocal" type="checkbox" id="useOneClickNsfw" v-model="useOneClickNsfw">
<label for="useOneClickNsfw">{{$t('settings.use_one_click_nsfw')}}</label>
</li>
</ul>
<li>
<input type="checkbox" id="stopGifs" v-model="stopGifs">
<label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
</li>
<li>
<input type="checkbox" id="loopVideo" v-model="loopVideoLocal">
<label for="loopVideo">{{$t('settings.loop_video')}}</label>
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
<li> <li>
<input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal"> <input
<label for="loopVideoSilentOnly">{{$t('settings.loop_video_silent_only')}}</label> id="hideMutedPosts"
<div v-if="!loopSilentAvailable" class="unavailable"> v-model="hideMutedPostsLocal"
<i class="icon-globe"/>! {{$t('settings.limited_availability')}} type="checkbox"
>
<label for="hideMutedPosts">{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsDefault }) }}</label>
</li>
<li>
<input
id="collapseMessageWithSubject"
v-model="collapseMessageWithSubjectLocal"
type="checkbox"
>
<label for="collapseMessageWithSubject">{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectDefault }) }}</label>
</li>
<li>
<input
id="streaming"
v-model="streamingLocal"
type="checkbox"
>
<label for="streaming">{{ $t('settings.streaming') }}</label>
<ul
class="setting-list suboptions"
:class="[{disabled: !streamingLocal}]"
>
<li>
<input
id="pauseOnUnfocused"
v-model="pauseOnUnfocusedLocal"
:disabled="!streamingLocal"
type="checkbox"
>
<label for="pauseOnUnfocused">{{ $t('settings.pause_on_unfocused') }}</label>
</li>
</ul>
</li>
<li>
<input
id="autoload"
v-model="autoLoadLocal"
type="checkbox"
>
<label for="autoload">{{ $t('settings.autoload') }}</label>
</li>
<li>
<input
id="hoverPreview"
v-model="hoverPreviewLocal"
type="checkbox"
>
<label for="hoverPreview">{{ $t('settings.reply_link_preview') }}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{ $t('settings.composing') }}</h2>
<ul class="setting-list">
<li>
<input
id="scopeCopy"
v-model="scopeCopyLocal"
type="checkbox"
>
<label for="scopeCopy">
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyDefault }) }}
</label>
</li>
<li>
<input
id="subjectHide"
v-model="alwaysShowSubjectInputLocal"
type="checkbox"
>
<label for="subjectHide">
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputDefault }) }}
</label>
</li>
<li>
<div>
{{ $t('settings.subject_line_behavior') }}
<label
for="subjectLineBehavior"
class="select"
>
<select
id="subjectLineBehavior"
v-model="subjectLineBehaviorLocal"
>
<option value="email">
{{ $t('settings.subject_line_email') }}
{{ subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : '' }}
</option>
<option value="masto">
{{ $t('settings.subject_line_mastodon') }}
{{ subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
</option>
<option value="noop">
{{ $t('settings.subject_line_noop') }}
{{ subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : '' }}
</option>
</select>
<i class="icon-down-open" />
</label>
</div>
</li>
<li v-if="postFormats.length > 0">
<div>
{{ $t('settings.post_status_content_type') }}
<label
for="postContentType"
class="select"
>
<select
id="postContentType"
v-model="postContentTypeLocal"
>
<option
v-for="postFormat in postFormats"
:key="postFormat"
:value="postFormat"
>
{{ $t(`post_status.content_type["${postFormat}"]`) }}
{{ postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : '' }}
</option>
</select>
<i class="icon-down-open" />
</label>
</div> </div>
</li> </li>
</ul>
</li>
<li>
<input type="checkbox" id="playVideosInModal" v-model="playVideosInModal">
<label for="playVideosInModal">{{$t('settings.play_videos_in_modal')}}</label>
</li>
<li>
<input type="checkbox" id="useContainFit" v-model="useContainFit">
<label for="useContainFit">{{$t('settings.use_contain_fit')}}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{$t('settings.notifications')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="webPushNotifications" v-model="webPushNotificationsLocal">
<label for="webPushNotifications">
{{$t('settings.enable_web_push_notifications')}}
</label>
</li>
</ul>
</div>
</div>
<div :label="$t('settings.theme')" >
<div class="setting-item">
<style-switcher></style-switcher>
</div>
</div>
<div :label="$t('settings.filtering')" >
<div class="setting-item">
<div class="select-multiple">
<span class="label">{{$t('settings.notification_visibility')}}</span>
<ul class="option-list">
<li>
<input type="checkbox" id="notification-visibility-likes" v-model="notificationVisibilityLocal.likes">
<label for="notification-visibility-likes">
{{$t('settings.notification_visibility_likes')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-repeats" v-model="notificationVisibilityLocal.repeats">
<label for="notification-visibility-repeats">
{{$t('settings.notification_visibility_repeats')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-follows" v-model="notificationVisibilityLocal.follows">
<label for="notification-visibility-follows">
{{$t('settings.notification_visibility_follows')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-mentions" v-model="notificationVisibilityLocal.mentions">
<label for="notification-visibility-mentions">
{{$t('settings.notification_visibility_mentions')}}
</label>
</li>
</ul>
</div>
<div>
{{$t('settings.replies_in_timeline')}}
<label for="replyVisibility" class="select">
<select id="replyVisibility" v-model="replyVisibilityLocal">
<option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
<option value="following">{{$t('settings.reply_visibility_following')}}</option>
<option value="self">{{$t('settings.reply_visibility_self')}}</option>
</select>
<i class="icon-down-open"/>
</label>
</div>
<div>
<input type="checkbox" id="hidePostStats" v-model="hidePostStatsLocal">
<label for="hidePostStats">
{{$t('settings.hide_post_stats')}} {{$t('settings.instance_default', { value: hidePostStatsDefault })}}
</label>
</div>
<div>
<input type="checkbox" id="hideUserStats" v-model="hideUserStatsLocal">
<label for="hideUserStats">
{{$t('settings.hide_user_stats')}} {{$t('settings.instance_default', { value: hideUserStatsDefault })}}
</label>
</div>
</div>
<div class="setting-item">
<div>
<p>{{$t('settings.filtering_explanation')}}</p>
<textarea id="muteWords" v-model="muteWordsString"></textarea>
</div>
<div>
<input type="checkbox" id="hideFilteredStatuses" v-model="hideFilteredStatusesLocal">
<label for="hideFilteredStatuses">
{{$t('settings.hide_filtered_statuses')}} {{$t('settings.instance_default', { value: hideFilteredStatusesDefault })}}
</label>
</div>
</div>
</div>
<div :label="$t('settings.version.title')" >
<div class="setting-item">
<ul class="setting-list">
<li>
<p>{{$t('settings.version.backend_version')}}</p>
<ul class="option-list">
<li> <li>
<a :href="backendVersionLink" target="_blank">{{backendVersion}}</a> <input
id="minimalScopesMode"
v-model="minimalScopesModeLocal"
type="checkbox"
>
<label for="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeDefault }) }}
</label>
</li>
<li>
<input
id="autohideFloatingPostButton"
v-model="autohideFloatingPostButtonLocal"
type="checkbox"
>
<label for="autohideFloatingPostButton">{{ $t('settings.autohide_floating_post_button') }}</label>
</li> </li>
</ul> </ul>
</li> </div>
<li>
<p>{{$t('settings.version.frontend_version')}}</p> <div class="setting-item">
<ul class="option-list"> <h2>{{ $t('settings.attachments') }}</h2>
<ul class="setting-list">
<li> <li>
<a :href="frontendVersionLink" target="_blank">{{frontendVersion}}</a> <input
id="hideAttachments"
v-model="hideAttachmentsLocal"
type="checkbox"
>
<label for="hideAttachments">{{ $t('settings.hide_attachments_in_tl') }}</label>
</li>
<li>
<input
id="hideAttachmentsInConv"
v-model="hideAttachmentsInConvLocal"
type="checkbox"
>
<label for="hideAttachmentsInConv">{{ $t('settings.hide_attachments_in_convo') }}</label>
</li>
<li>
<label for="maxThumbnails">{{ $t('settings.max_thumbnails') }}</label>
<input
id="maxThumbnails"
v-model.number="maxThumbnails"
class="number-input"
type="number"
min="0"
step="1"
>
</li>
<li>
<input
id="hideNsfw"
v-model="hideNsfwLocal"
type="checkbox"
>
<label for="hideNsfw">{{ $t('settings.nsfw_clickthrough') }}</label>
</li>
<ul class="setting-list suboptions">
<li>
<input
id="preloadImage"
v-model="preloadImage"
:disabled="!hideNsfwLocal"
type="checkbox"
>
<label for="preloadImage">{{ $t('settings.preload_images') }}</label>
</li>
<li>
<input
id="useOneClickNsfw"
v-model="useOneClickNsfw"
:disabled="!hideNsfwLocal"
type="checkbox"
>
<label for="useOneClickNsfw">{{ $t('settings.use_one_click_nsfw') }}</label>
</li>
</ul>
<li>
<input
id="stopGifs"
v-model="stopGifs"
type="checkbox"
>
<label for="stopGifs">{{ $t('settings.stop_gifs') }}</label>
</li>
<li>
<input
id="loopVideo"
v-model="loopVideoLocal"
type="checkbox"
>
<label for="loopVideo">{{ $t('settings.loop_video') }}</label>
<ul
class="setting-list suboptions"
:class="[{disabled: !streamingLocal}]"
>
<li>
<input
id="loopVideoSilentOnly"
v-model="loopVideoSilentOnlyLocal"
:disabled="!loopVideoLocal || !loopSilentAvailable"
type="checkbox"
>
<label for="loopVideoSilentOnly">{{ $t('settings.loop_video_silent_only') }}</label>
<div
v-if="!loopSilentAvailable"
class="unavailable"
>
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
</div>
</li>
</ul>
</li>
<li>
<input
id="playVideosInModal"
v-model="playVideosInModal"
type="checkbox"
>
<label for="playVideosInModal">{{ $t('settings.play_videos_in_modal') }}</label>
</li>
<li>
<input
id="useContainFit"
v-model="useContainFit"
type="checkbox"
>
<label for="useContainFit">{{ $t('settings.use_contain_fit') }}</label>
</li> </li>
</ul> </ul>
</li> </div>
</ul>
</div> <div class="setting-item">
</div> <h2>{{ $t('settings.notifications') }}</h2>
</tab-switcher> <ul class="setting-list">
</keep-alive> <li>
<input
id="webPushNotifications"
v-model="webPushNotificationsLocal"
type="checkbox"
>
<label for="webPushNotifications">
{{ $t('settings.enable_web_push_notifications') }}
</label>
</li>
</ul>
</div>
</div>
<div :label="$t('settings.theme')">
<div class="setting-item">
<style-switcher />
</div>
</div>
<div :label="$t('settings.filtering')">
<div class="setting-item">
<div class="select-multiple">
<span class="label">{{ $t('settings.notification_visibility') }}</span>
<ul class="option-list">
<li>
<input
id="notification-visibility-likes"
v-model="notificationVisibilityLocal.likes"
type="checkbox"
>
<label for="notification-visibility-likes">
{{ $t('settings.notification_visibility_likes') }}
</label>
</li>
<li>
<input
id="notification-visibility-repeats"
v-model="notificationVisibilityLocal.repeats"
type="checkbox"
>
<label for="notification-visibility-repeats">
{{ $t('settings.notification_visibility_repeats') }}
</label>
</li>
<li>
<input
id="notification-visibility-follows"
v-model="notificationVisibilityLocal.follows"
type="checkbox"
>
<label for="notification-visibility-follows">
{{ $t('settings.notification_visibility_follows') }}
</label>
</li>
<li>
<input
id="notification-visibility-mentions"
v-model="notificationVisibilityLocal.mentions"
type="checkbox"
>
<label for="notification-visibility-mentions">
{{ $t('settings.notification_visibility_mentions') }}
</label>
</li>
</ul>
</div>
<div>
{{ $t('settings.replies_in_timeline') }}
<label
for="replyVisibility"
class="select"
>
<select
id="replyVisibility"
v-model="replyVisibilityLocal"
>
<option
value="all"
selected
>{{ $t('settings.reply_visibility_all') }}</option>
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
</select>
<i class="icon-down-open" />
</label>
</div>
<div>
<input
id="hidePostStats"
v-model="hidePostStatsLocal"
type="checkbox"
>
<label for="hidePostStats">
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsDefault }) }}
</label>
</div>
<div>
<input
id="hideUserStats"
v-model="hideUserStatsLocal"
type="checkbox"
>
<label for="hideUserStats">
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsDefault }) }}
</label>
</div>
</div>
<div class="setting-item">
<div>
<p>{{ $t('settings.filtering_explanation') }}</p>
<textarea
id="muteWords"
v-model="muteWordsString"
/>
</div>
<div>
<input
id="hideFilteredStatuses"
v-model="hideFilteredStatusesLocal"
type="checkbox"
>
<label for="hideFilteredStatuses">
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesDefault }) }}
</label>
</div>
</div>
</div>
<div :label="$t('settings.version.title')">
<div class="setting-item">
<ul class="setting-list">
<li>
<p>{{ $t('settings.version.backend_version') }}</p>
<ul class="option-list">
<li>
<a
:href="backendVersionLink"
target="_blank"
>{{ backendVersion }}</a>
</li>
</ul>
</li>
<li>
<p>{{ $t('settings.version.frontend_version') }}</p>
<ul class="option-list">
<li>
<a
:href="frontendVersionLink"
target="_blank"
>{{ frontendVersion }}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</tab-switcher>
</keep-alive>
</div>
</div> </div>
</div>
</template> </template>
<script src="./settings.js"> <script src="./settings.js">
</script> </script>

View file

@ -1,134 +1,206 @@
<template> <template>
<div class="shadow-control" :class="{ disabled: !present }"> <div
<div class="shadow-preview-container"> class="shadow-control"
<div :disabled="!present" class="y-shift-control"> :class="{ disabled: !present }"
<input >
v-model="selected.y" <div class="shadow-preview-container">
<div
:disabled="!present" :disabled="!present"
class="input-number" class="y-shift-control"
type="number"> >
<div class="wrap">
<input <input
v-model="selected.y" v-model="selected.y"
:disabled="!present" :disabled="!present"
class="input-range" class="input-number"
type="range" type="number"
max="20" >
min="-20"> <div class="wrap">
<input
v-model="selected.y"
:disabled="!present"
class="input-range"
type="range"
max="20"
min="-20"
>
</div>
</div> </div>
</div> <div class="preview-window">
<div class="preview-window"> <div
<div class="preview-block" :style="style"></div> class="preview-block"
</div> :style="style"
<div :disabled="!present" class="x-shift-control"> />
<input </div>
v-model="selected.x" <div
:disabled="!present" :disabled="!present"
class="input-number" class="x-shift-control"
type="number"> >
<div class="wrap">
<input <input
v-model="selected.x" v-model="selected.x"
:disabled="!present" :disabled="!present"
class="input-number"
type="number"
>
<div class="wrap">
<input
v-model="selected.x"
:disabled="!present"
class="input-range"
type="range"
max="20"
min="-20"
>
</div>
</div>
</div>
<div class="shadow-tweak">
<div
:disabled="usingFallback"
class="id-control style-control"
>
<label
for="shadow-switcher"
class="select"
:disabled="!ready || usingFallback"
>
<select
id="shadow-switcher"
v-model="selectedId"
class="shadow-switcher"
:disabled="!ready || usingFallback"
>
<option
v-for="(shadow, index) in cValue"
:value="index"
>
{{ $t('settings.style.shadows.shadow_id', { value: index }) }}
</option>
</select>
<i class="icon-down-open" />
</label>
<button
class="btn btn-default"
:disabled="!ready || !present"
@click="del"
>
<i class="icon-cancel" />
</button>
<button
class="btn btn-default"
:disabled="!moveUpValid"
@click="moveUp"
>
<i class="icon-up-open" />
</button>
<button
class="btn btn-default"
:disabled="!moveDnValid"
@click="moveDn"
>
<i class="icon-down-open" />
</button>
<button
class="btn btn-default"
:disabled="usingFallback"
@click="add"
>
<i class="icon-plus" />
</button>
</div>
<div
:disabled="!present"
class="inset-control style-control"
>
<label
for="inset"
class="label"
>
{{ $t('settings.style.shadows.inset') }}
</label>
<input
id="inset"
v-model="selected.inset"
:disabled="!present"
name="inset"
class="input-inset"
type="checkbox"
>
<label
class="checkbox-label"
for="inset"
/>
</div>
<div
:disabled="!present"
class="blur-control style-control"
>
<label
for="spread"
class="label"
>
{{ $t('settings.style.shadows.blur') }}
</label>
<input
id="blur"
v-model="selected.blur"
:disabled="!present"
name="blur"
class="input-range" class="input-range"
type="range" type="range"
max="20" max="20"
min="-20"> min="0"
>
<input
v-model="selected.blur"
:disabled="!present"
class="input-number"
type="number"
min="0"
>
</div> </div>
<div
:disabled="!present"
class="spread-control style-control"
>
<label
for="spread"
class="label"
>
{{ $t('settings.style.shadows.spread') }}
</label>
<input
id="spread"
v-model="selected.spread"
:disabled="!present"
name="spread"
class="input-range"
type="range"
max="20"
min="-20"
>
<input
v-model="selected.spread"
:disabled="!present"
class="input-number"
type="number"
>
</div>
<ColorInput
v-model="selected.color"
:disabled="!present"
:label="$t('settings.style.common.color')"
name="shadow"
/>
<OpacityInput
v-model="selected.alpha"
:disabled="!present"
/>
<p>
{{ $t('settings.style.shadows.hint') }}
</p>
</div> </div>
</div> </div>
<div class="shadow-tweak">
<div :disabled="usingFallback" class="id-control style-control">
<label for="shadow-switcher" class="select" :disabled="!ready || usingFallback">
<select
v-model="selectedId" class="shadow-switcher"
:disabled="!ready || usingFallback"
id="shadow-switcher">
<option v-for="(shadow, index) in cValue" :value="index">
{{$t('settings.style.shadows.shadow_id', { value: index })}}
</option>
</select>
<i class="icon-down-open"/>
</label>
<button class="btn btn-default" :disabled="!ready || !present" @click="del">
<i class="icon-cancel"/>
</button>
<button class="btn btn-default" :disabled="!moveUpValid" @click="moveUp">
<i class="icon-up-open"/>
</button>
<button class="btn btn-default" :disabled="!moveDnValid" @click="moveDn">
<i class="icon-down-open"/>
</button>
<button class="btn btn-default" :disabled="usingFallback" @click="add">
<i class="icon-plus"/>
</button>
</div>
<div :disabled="!present" class="inset-control style-control">
<label for="inset" class="label">
{{$t('settings.style.shadows.inset')}}
</label>
<input
v-model="selected.inset"
:disabled="!present"
name="inset"
id="inset"
class="input-inset"
type="checkbox">
<label class="checkbox-label" for="inset"></label>
</div>
<div :disabled="!present" class="blur-control style-control">
<label for="spread" class="label">
{{$t('settings.style.shadows.blur')}}
</label>
<input
v-model="selected.blur"
:disabled="!present"
name="blur"
id="blur"
class="input-range"
type="range"
max="20"
min="0">
<input
v-model="selected.blur"
:disabled="!present"
class="input-number"
type="number"
min="0">
</div>
<div :disabled="!present" class="spread-control style-control">
<label for="spread" class="label">
{{$t('settings.style.shadows.spread')}}
</label>
<input
v-model="selected.spread"
:disabled="!present"
name="spread"
id="spread"
class="input-range"
type="range"
max="20"
min="-20">
<input
v-model="selected.spread"
:disabled="!present"
class="input-number"
type="number">
</div>
<ColorInput
v-model="selected.color"
:disabled="!present"
:label="$t('settings.style.common.color')"
name="shadow"/>
<OpacityInput
v-model="selected.alpha"
:disabled="!present"/>
<p>
{{$t('settings.style.shadows.hint')}}
</p>
</div>
</div>
</template> </template>
<script src="./shadow_control.js" ></script> <script src="./shadow_control.js" ></script>

View file

@ -1,63 +1,98 @@
<template> <template>
<div class="side-drawer-container" <div
class="side-drawer-container"
:class="{ 'side-drawer-container-closed': closed, 'side-drawer-container-open': !closed }" :class="{ 'side-drawer-container-closed': closed, 'side-drawer-container-open': !closed }"
> >
<div class="side-drawer-darken" :class="{ 'side-drawer-darken-closed': closed}" /> <div
<div class="side-drawer" class="side-drawer-darken"
:class="{ 'side-drawer-darken-closed': closed}"
/>
<div
class="side-drawer"
:class="{'side-drawer-closed': closed}" :class="{'side-drawer-closed': closed}"
@touchstart="touchStart" @touchstart="touchStart"
@touchmove="touchMove" @touchmove="touchMove"
> >
<div class="side-drawer-heading" @click="toggleDrawer"> <div
<UserCard :user="currentUser" :hideBio="true" v-if="currentUser"/> class="side-drawer-heading"
<div class="side-drawer-logo-wrapper" v-else> @click="toggleDrawer"
<img :src="logo"/> >
<span>{{sitename}}</span> <UserCard
v-if="currentUser"
:user="currentUser"
:hide-bio="true"
/>
<div
v-else
class="side-drawer-logo-wrapper"
>
<img :src="logo">
<span>{{ sitename }}</span>
</div> </div>
</div> </div>
<ul> <ul>
<li v-if="!currentUser" @click="toggleDrawer"> <li
v-if="!currentUser"
@click="toggleDrawer"
>
<router-link :to="{ name: 'login' }"> <router-link :to="{ name: 'login' }">
{{ $t("login.login") }} {{ $t("login.login") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser" @click="toggleDrawer"> <li
v-if="currentUser"
@click="toggleDrawer"
>
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
{{ $t("nav.dms") }} {{ $t("nav.dms") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser" @click="toggleDrawer"> <li
v-if="currentUser"
@click="toggleDrawer"
>
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
{{ $t("nav.interactions") }} {{ $t("nav.interactions") }}
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ul> <ul>
<li v-if="currentUser" @click="toggleDrawer"> <li
v-if="currentUser"
@click="toggleDrawer"
>
<router-link :to="{ name: 'friends' }"> <router-link :to="{ name: 'friends' }">
{{ $t("nav.timeline") }} {{ $t("nav.timeline") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser && currentUser.locked" @click="toggleDrawer"> <li
<router-link to='/friend-requests'> v-if="currentUser && currentUser.locked"
@click="toggleDrawer"
>
<router-link to="/friend-requests">
{{ $t("nav.friend_requests") }} {{ $t("nav.friend_requests") }}
<span v-if='followRequestCount > 0' class="badge follow-request-count"> <span
{{followRequestCount}} v-if="followRequestCount > 0"
class="badge follow-request-count"
>
{{ followRequestCount }}
</span> </span>
</router-link> </router-link>
</li> </li>
<li @click="toggleDrawer"> <li @click="toggleDrawer">
<router-link to='/main/public'> <router-link to="/main/public">
{{ $t("nav.public_tl") }} {{ $t("nav.public_tl") }}
</router-link> </router-link>
</li> </li>
<li @click="toggleDrawer"> <li @click="toggleDrawer">
<router-link to='/main/all'> <router-link to="/main/all">
{{ $t("nav.twkn") }} {{ $t("nav.twkn") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser && chat" @click="toggleDrawer"> <li
v-if="currentUser && chat"
@click="toggleDrawer"
>
<router-link :to="{ name: 'chat' }"> <router-link :to="{ name: 'chat' }">
{{ $t("nav.chat") }} {{ $t("nav.chat") }}
</router-link> </router-link>
@ -69,7 +104,10 @@
{{ $t("nav.user_search") }} {{ $t("nav.user_search") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser && suggestionsEnabled" @click="toggleDrawer"> <li
v-if="currentUser && suggestionsEnabled"
@click="toggleDrawer"
>
<router-link :to="{ name: 'who-to-follow' }"> <router-link :to="{ name: 'who-to-follow' }">
{{ $t("nav.who_to_follow") }} {{ $t("nav.who_to_follow") }}
</router-link> </router-link>
@ -84,17 +122,24 @@
{{ $t("nav.about") }} {{ $t("nav.about") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser" @click="toggleDrawer"> <li
<a @click="doLogout" href="#"> v-if="currentUser"
@click="toggleDrawer"
>
<a
href="#"
@click="doLogout"
>
{{ $t("login.logout") }} {{ $t("login.logout") }}
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="side-drawer-click-outside" <div
@click.stop.prevent="toggleDrawer" class="side-drawer-click-outside"
:class="{'side-drawer-click-outside-closed': closed}" :class="{'side-drawer-click-outside-closed': closed}"
></div> @click.stop.prevent="toggleDrawer"
/>
</div> </div>
</template> </template>

View file

@ -1,187 +1,424 @@
<template> <template>
<div class="status-el" v-if="!hideStatus" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]"> <div
<div v-if="error" class="alert error"> v-if="!hideStatus"
{{error}} class="status-el"
<i class="button-icon icon-cancel" @click="clearError"></i> :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]"
>
<div
v-if="error"
class="alert error"
>
{{ error }}
<i
class="button-icon icon-cancel"
@click="clearError"
/>
</div> </div>
<template v-if="muted && !isPreview"> <template v-if="muted && !isPreview">
<div class="media status container muted"> <div class="media status container muted">
<small> <small>
<router-link :to="userProfileLink"> <router-link :to="userProfileLink">
{{status.user.screen_name}} {{ status.user.screen_name }}
</router-link> </router-link>
</small> </small>
<small class="muteWords">{{muteWordHits.join(', ')}}</small> <small class="muteWords">{{ muteWordHits.join(', ') }}</small>
<a href="#" class="unmute" @click.prevent="toggleMute"><i class="button-icon icon-eye-off"></i></a> <a
href="#"
class="unmute"
@click.prevent="toggleMute"
><i class="button-icon icon-eye-off" /></a>
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div v-if="showPinned && statusoid.pinned" class="status-pin"> <div
<i class="fa icon-pin faint"></i> v-if="showPinned && statusoid.pinned"
<span class="faint">{{$t('status.pinned')}}</span> class="status-pin"
>
<i class="fa icon-pin faint" />
<span class="faint">{{ $t('status.pinned') }}</span>
</div> </div>
<div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info"> <div
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :user="statusoid.user"/> v-if="retweet && !noHeading && !inConversation"
:class="[repeaterClass, { highlighted: repeaterStyle }]"
:style="[repeaterStyle]"
class="media container retweet-info"
>
<UserAvatar
v-if="retweet"
class="media-left"
:better-shadow="betterShadow"
:user="statusoid.user"
/>
<div class="media-body faint"> <div class="media-body faint">
<span class="user-name"> <span class="user-name">
<router-link v-if="retweeterHtml" :to="retweeterProfileLink" v-html="retweeterHtml"/> <router-link
<router-link v-else :to="retweeterProfileLink">{{retweeter}}</router-link> v-if="retweeterHtml"
:to="retweeterProfileLink"
v-html="retweeterHtml"
/>
<router-link
v-else
:to="retweeterProfileLink"
>{{ retweeter }}</router-link>
</span> </span>
<i class='fa icon-retweet retweeted' :title="$t('tool_tip.repeat')"></i> <i
{{$t('timeline.repeated')}} class="fa icon-retweet retweeted"
:title="$t('tool_tip.repeat')"
/>
{{ $t('timeline.repeated') }}
</div> </div>
</div> </div>
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]" :style="[ userStyle ]" class="media status" :data-tags="tags"> <div
<div v-if="!noHeading" class="media-left"> :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]"
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded"> :style="[ userStyle ]"
<UserAvatar :compact="compact" :betterShadow="betterShadow" :user="status.user"/> class="media status"
:data-tags="tags"
>
<div
v-if="!noHeading"
class="media-left"
>
<router-link
:to="userProfileLink"
@click.stop.prevent.capture.native="toggleUserExpanded"
>
<UserAvatar
:compact="compact"
:better-shadow="betterShadow"
:user="status.user"
/>
</router-link> </router-link>
</div> </div>
<div class="status-body"> <div class="status-body">
<UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard" v-if="userExpanded"/> <UserCard
<div v-if="!noHeading" class="media-heading"> v-if="userExpanded"
:user="status.user"
:rounded="true"
:bordered="true"
class="status-usercard"
/>
<div
v-if="!noHeading"
class="media-heading"
>
<div class="heading-name-row"> <div class="heading-name-row">
<div class="name-and-account-name"> <div class="name-and-account-name">
<h4 class="user-name" v-if="status.user.name_html" v-html="status.user.name_html"></h4> <h4
<h4 class="user-name" v-else>{{status.user.name}}</h4> v-if="status.user.name_html"
<router-link class="account-name" :to="userProfileLink"> class="user-name"
{{status.user.screen_name}} v-html="status.user.name_html"
/>
<h4
v-else
class="user-name"
>
{{ status.user.name }}
</h4>
<router-link
class="account-name"
:to="userProfileLink"
>
{{ status.user.screen_name }}
</router-link> </router-link>
</div> </div>
<span class="heading-right"> <span class="heading-right">
<router-link class="timeago faint-link" :to="{ name: 'conversation', params: { id: status.id } }"> <router-link
<Timeago :time="status.created_at" :auto-update="60"></Timeago> class="timeago faint-link"
:to="{ name: 'conversation', params: { id: status.id } }"
>
<Timeago
:time="status.created_at"
:auto-update="60"
/>
</router-link> </router-link>
<div class="button-icon visibility-icon" v-if="status.visibility"> <div
<i :class="visibilityIcon(status.visibility)" :title="status.visibility | capitalize"></i> v-if="status.visibility"
class="button-icon visibility-icon"
>
<i
:class="visibilityIcon(status.visibility)"
:title="status.visibility | capitalize"
/>
</div> </div>
<a :href="status.external_url" target="_blank" v-if="!status.is_local && !isPreview" class="source_url" title="Source"> <a
<i class="button-icon icon-link-ext-alt"></i> v-if="!status.is_local && !isPreview"
:href="status.external_url"
target="_blank"
class="source_url"
title="Source"
>
<i class="button-icon icon-link-ext-alt" />
</a> </a>
<template v-if="expandable && !isPreview"> <template v-if="expandable && !isPreview">
<a href="#" @click.prevent="toggleExpanded" title="Expand"> <a
<i class="button-icon icon-plus-squared"></i> href="#"
title="Expand"
@click.prevent="toggleExpanded"
>
<i class="button-icon icon-plus-squared" />
</a> </a>
</template> </template>
<a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="button-icon icon-eye-off"></i></a> <a
v-if="unmuted"
href="#"
@click.prevent="toggleMute"
><i class="button-icon icon-eye-off" /></a>
</span> </span>
</div> </div>
<div class="heading-reply-row"> <div class="heading-reply-row">
<div v-if="isReply" class="reply-to-and-accountname"> <div
<a class="reply-to" v-if="isReply"
href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)" class="reply-to-and-accountname"
>
<a
class="reply-to"
href="#"
:aria-label="$t('tool_tip.reply')" :aria-label="$t('tool_tip.reply')"
@click.prevent="gotoOriginal(status.in_reply_to_status_id)"
@mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)" @mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)"
@mouseleave.prevent.stop="replyLeave()" @mouseleave.prevent.stop="replyLeave()"
> >
<i class="button-icon icon-reply" v-if="!isPreview"></i> <i
<span class="faint-link reply-to-text">{{$t('status.reply_to')}}</span> v-if="!isPreview"
class="button-icon icon-reply"
/>
<span class="faint-link reply-to-text">{{ $t('status.reply_to') }}</span>
</a> </a>
<router-link :to="replyProfileLink"> <router-link :to="replyProfileLink">
{{replyToName}} {{ replyToName }}
</router-link> </router-link>
<span class="faint replies-separator" v-if="replies && replies.length"> <span
v-if="replies && replies.length"
class="faint replies-separator"
>
- -
</span> </span>
</div> </div>
<div class="replies" v-if="inConversation && !isPreview"> <div
<span class="faint" v-if="replies && replies.length">{{$t('status.replies_list')}}</span> v-if="inConversation && !isPreview"
<span class="reply-link faint" v-if="replies" v-for="reply in replies"> class="replies"
<a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}</a> >
<span
v-if="replies && replies.length"
class="faint"
>{{ $t('status.replies_list') }}</span>
<span
v-for="reply in replies"
v-if="replies"
class="reply-link faint"
>
<a
href="#"
@click.prevent="gotoOriginal(reply.id)"
@mouseenter="replyEnter(reply.id, $event)"
@mouseout="replyLeave()"
>{{ reply.name }}</a>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<div v-if="showPreview" class="status-preview-container"> <div
<status class="status-preview" v-if="showPreview"
class="status-preview-container"
>
<status
v-if="preview" v-if="preview"
:isPreview="true" class="status-preview"
:is-preview="true"
:statusoid="preview" :statusoid="preview"
:compact="true" :compact="true"
/> />
<div v-else class="status-preview status-preview-loading"> <div
<i class="icon-spin4 animate-spin"></i> v-else
class="status-preview status-preview-loading"
>
<i class="icon-spin4 animate-spin" />
</div> </div>
</div> </div>
<div class="status-content-wrapper" :class="{ 'tall-status': !showingLongSubject }" v-if="longSubject"> <div
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingLongSubject" href="#" @click.prevent="showingLongSubject=true">{{$t("general.show_more")}}</a> v-if="longSubject"
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml"></div> class="status-content-wrapper"
<a v-if="showingLongSubject" href="#" class="status-unhider" @click.prevent="showingLongSubject=false">{{$t("general.show_less")}}</a> :class="{ 'tall-status': !showingLongSubject }"
>
<a
v-if="!showingLongSubject"
class="tall-status-hider"
:class="{ 'tall-status-hider_focused': isFocused }"
href="#"
@click.prevent="showingLongSubject=true"
>{{ $t("general.show_more") }}</a>
<div
class="status-content media-body"
@click.prevent="linkClicked"
v-html="contentHtml"
/>
<a
v-if="showingLongSubject"
href="#"
class="status-unhider"
@click.prevent="showingLongSubject=false"
>{{ $t("general.show_less") }}</a>
</div> </div>
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" v-else> <div
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a> v-else
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml" v-if="!hideSubjectStatus"></div> :class="{'tall-status': hideTallStatus}"
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary_html" v-else></div> class="status-content-wrapper"
<a v-if="hideSubjectStatus" href="#" class="cw-status-hider" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a> >
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">{{$t("general.show_less")}}</a> <a
v-if="hideTallStatus"
class="tall-status-hider"
:class="{ 'tall-status-hider_focused': isFocused }"
href="#"
@click.prevent="toggleShowMore"
>{{ $t("general.show_more") }}</a>
<div
v-if="!hideSubjectStatus"
class="status-content media-body"
@click.prevent="linkClicked"
v-html="contentHtml"
/>
<div
v-else
class="status-content media-body"
@click.prevent="linkClicked"
v-html="status.summary_html"
/>
<a
v-if="hideSubjectStatus"
href="#"
class="cw-status-hider"
@click.prevent="toggleShowMore"
>{{ $t("general.show_more") }}</a>
<a
v-if="showingMore"
href="#"
class="status-unhider"
@click.prevent="toggleShowMore"
>{{ $t("general.show_less") }}</a>
</div> </div>
<div v-if="status.poll && status.poll.options"> <div v-if="status.poll && status.poll.options">
<poll :base-poll="status.poll" /> <poll :base-poll="status.poll" />
</div> </div>
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body"> <div
v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)"
class="attachments media-body"
>
<attachment <attachment
class="non-gallery"
v-for="attachment in nonGalleryAttachments" v-for="attachment in nonGalleryAttachments"
:key="attachment.id"
class="non-gallery"
:size="attachmentSize" :size="attachmentSize"
:nsfw="nsfwClickthrough" :nsfw="nsfwClickthrough"
:attachment="attachment" :attachment="attachment"
:allowPlay="true" :allow-play="true"
:setMedia="setMedia()" :set-media="setMedia()"
:key="attachment.id"
/> />
<gallery <gallery
v-if="galleryAttachments.length > 0" v-if="galleryAttachments.length > 0"
:nsfw="nsfwClickthrough" :nsfw="nsfwClickthrough"
:attachments="galleryAttachments" :attachments="galleryAttachments"
:setMedia="setMedia()" :set-media="setMedia()"
/> />
</div> </div>
<div v-if="status.card && !hideSubjectStatus && !noHeading" class="link-preview media-body"> <div
<link-preview :card="status.card" :size="attachmentSize" :nsfw="nsfwClickthrough" /> v-if="status.card && !hideSubjectStatus && !noHeading"
class="link-preview media-body"
>
<link-preview
:card="status.card"
:size="attachmentSize"
:nsfw="nsfwClickthrough"
/>
</div> </div>
<transition name="fade"> <transition name="fade">
<div class="favs-repeated-users" v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0"> <div
v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0"
class="favs-repeated-users"
>
<div class="stats"> <div class="stats">
<div class="stat-count" v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0"> <div
v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0"
class="stat-count"
>
<a class="stat-title">{{ $t('status.repeats') }}</a> <a class="stat-title">{{ $t('status.repeats') }}</a>
<div class="stat-number">{{ statusFromGlobalRepository.rebloggedBy.length }}</div> <div class="stat-number">
{{ statusFromGlobalRepository.rebloggedBy.length }}
</div>
</div> </div>
<div class="stat-count" v-if="statusFromGlobalRepository.favoritedBy && statusFromGlobalRepository.favoritedBy.length > 0"> <div
v-if="statusFromGlobalRepository.favoritedBy && statusFromGlobalRepository.favoritedBy.length > 0"
class="stat-count"
>
<a class="stat-title">{{ $t('status.favorites') }}</a> <a class="stat-title">{{ $t('status.favorites') }}</a>
<div class="stat-number">{{ statusFromGlobalRepository.favoritedBy.length }}</div> <div class="stat-number">
{{ statusFromGlobalRepository.favoritedBy.length }}
</div>
</div> </div>
<div class="avatar-row"> <div class="avatar-row">
<AvatarList :users="combinedFavsAndRepeatsUsers"></AvatarList> <AvatarList :users="combinedFavsAndRepeatsUsers" />
</div> </div>
</div> </div>
</div> </div>
</transition> </transition>
<div v-if="!noHeading && !isPreview" class='status-actions media-body'> <div
v-if="!noHeading && !isPreview"
class="status-actions media-body"
>
<div> <div>
<i class="button-icon icon-reply" v-on:click.prevent="toggleReplying" :title="$t('tool_tip.reply')" :class="{'button-icon-active': replying}" v-if="loggedIn"/> <i
<i class="button-icon button-icon-disabled icon-reply" :title="$t('tool_tip.reply')" v-else /> v-if="loggedIn"
<span v-if="status.replies_count > 0">{{status.replies_count}}</span> class="button-icon icon-reply"
:title="$t('tool_tip.reply')"
:class="{'button-icon-active': replying}"
@click.prevent="toggleReplying"
/>
<i
v-else
class="button-icon button-icon-disabled icon-reply"
:title="$t('tool_tip.reply')"
/>
<span v-if="status.replies_count > 0">{{ status.replies_count }}</span>
</div> </div>
<retweet-button :visibility='status.visibility' :loggedIn='loggedIn' :status='status'></retweet-button> <retweet-button
<favorite-button :loggedIn='loggedIn' :status='status'></favorite-button> :visibility="status.visibility"
<extra-buttons :status="status" @onError="showError" @onSuccess="clearError"></extra-buttons> :logged-in="loggedIn"
:status="status"
/>
<favorite-button
:logged-in="loggedIn"
:status="status"
/>
<extra-buttons
:status="status"
@onError="showError"
@onSuccess="clearError"
/>
</div> </div>
</div> </div>
</div> </div>
<div class="container" v-if="replying"> <div
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :copy-message-scope="status.visibility" :subject="replySubject" v-on:posted="toggleReplying"/> v-if="replying"
class="container"
>
<post-status-form
class="reply-body"
:reply-to="status.id"
:attentions="status.attentions"
:replied-user="status.user"
:copy-message-scope="status.visibility"
:subject="replySubject"
@posted="toggleReplying"
/>
</div> </div>
</template> </template>
</div> </div>

View file

@ -1,7 +1,19 @@
<template> <template>
<div class='still-image' :class='{ animated: animated }' > <div
<canvas ref="canvas" v-if="animated"></canvas> class="still-image"
<img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad" @error="onError"/> :class="{ animated: animated }"
>
<canvas
v-if="animated"
ref="canvas"
/>
<img
ref="src"
:src="src"
:referrerpolicy="referrerpolicy"
@load="onLoad"
@error="onError"
>
</div> </div>
</template> </template>

View file

@ -1,78 +1,101 @@
<template> <template>
<div class="panel dummy"> <div class="panel dummy">
<div class="panel-heading"> <div class="panel-heading">
<div class="title"> <div class="title">
{{$t('settings.style.preview.header')}} {{ $t('settings.style.preview.header') }}
<span class="badge badge-notification"> <span class="badge badge-notification">
99 99
</span>
</div>
<span class="faint">
{{ $t('settings.style.preview.header_faint') }}
</span> </span>
</div> <span class="alert error">
<span class="faint"> {{ $t('settings.style.preview.error') }}
{{$t('settings.style.preview.header_faint')}}
</span>
<span class="alert error">
{{$t('settings.style.preview.error')}}
</span>
<button class="btn">
{{$t('settings.style.preview.button')}}
</button>
</div>
<div class="panel-body theme-preview-content">
<div class="post">
<div class="avatar">
( ͡° ͜ʖ ͡°)
</div>
<div class="content">
<h4>
{{$t('settings.style.preview.content')}}
</h4>
<i18n path="settings.style.preview.text">
<code style="font-family: var(--postCodeFont)">
{{$t('settings.style.preview.mono')}}
</code>
<a style="color: var(--link)">
{{$t('settings.style.preview.link')}}
</a>
</i18n>
<div class="icons">
<i style="color: var(--cBlue)" class="button-icon icon-reply"/>
<i style="color: var(--cGreen)" class="button-icon icon-retweet"/>
<i style="color: var(--cOrange)" class="button-icon icon-star"/>
<i style="color: var(--cRed)" class="button-icon icon-cancel"/>
</div>
</div>
</div>
<div class="after-post">
<div class="avatar-alt">
:^)
</div>
<div class="content">
<i18n path="settings.style.preview.fine_print" tag="span" class="faint">
<a style="color: var(--faintLink)">
{{$t('settings.style.preview.faint_link')}}
</a>
</i18n>
</div>
</div>
<div class="separator"></div>
<span class="alert error">
{{$t('settings.style.preview.error')}}
</span>
<input :value="$t('settings.style.preview.input')" type="text">
<div class="actions">
<span class="checkbox">
<input checked="very yes" type="checkbox" id="preview_checkbox">
<label for="preview_checkbox">{{$t('settings.style.preview.checkbox')}}</label>
</span> </span>
<button class="btn"> <button class="btn">
{{$t('settings.style.preview.button')}} {{ $t('settings.style.preview.button') }}
</button> </button>
</div> </div>
<div class="panel-body theme-preview-content">
<div class="post">
<div class="avatar">
( ͡° ͜ʖ ͡°)
</div>
<div class="content">
<h4>
{{ $t('settings.style.preview.content') }}
</h4>
<i18n path="settings.style.preview.text">
<code style="font-family: var(--postCodeFont)">
{{ $t('settings.style.preview.mono') }}
</code>
<a style="color: var(--link)">
{{ $t('settings.style.preview.link') }}
</a>
</i18n>
<div class="icons">
<i
style="color: var(--cBlue)"
class="button-icon icon-reply"
/>
<i
style="color: var(--cGreen)"
class="button-icon icon-retweet"
/>
<i
style="color: var(--cOrange)"
class="button-icon icon-star"
/>
<i
style="color: var(--cRed)"
class="button-icon icon-cancel"
/>
</div>
</div>
</div>
<div class="after-post">
<div class="avatar-alt">
:^)
</div>
<div class="content">
<i18n
path="settings.style.preview.fine_print"
tag="span"
class="faint"
>
<a style="color: var(--faintLink)">
{{ $t('settings.style.preview.faint_link') }}
</a>
</i18n>
</div>
</div>
<div class="separator" />
<span class="alert error">
{{ $t('settings.style.preview.error') }}
</span>
<input
:value="$t('settings.style.preview.input')"
type="text"
>
<div class="actions">
<span class="checkbox">
<input
id="preview_checkbox"
checked="very yes"
type="checkbox"
>
<label for="preview_checkbox">{{ $t('settings.style.preview.checkbox') }}</label>
</span>
<button class="btn">
{{ $t('settings.style.preview.button') }}
</button>
</div>
</div>
</div> </div>
</div>
</template> </template>

View file

@ -1,274 +1,591 @@
<template> <template>
<div class="style-switcher"> <div class="style-switcher">
<div class="presets-container"> <div class="presets-container">
<div class="save-load"> <div class="save-load">
<export-import <export-import
:exportObject='exportedTheme' :export-object="exportedTheme"
:exportLabel='$t("settings.export_theme")' :export-label="$t(&quot;settings.export_theme&quot;)"
:importLabel='$t("settings.import_theme")' :import-label="$t(&quot;settings.import_theme&quot;)"
:importFailedText='$t("settings.invalid_theme_imported")' :import-failed-text="$t(&quot;settings.invalid_theme_imported&quot;)"
:onImport='onImport' :on-import="onImport"
:validator='importValidator'> :validator="importValidator"
<template slot="before"> >
<div class="presets"> <template slot="before">
{{$t('settings.presets')}} <div class="presets">
<label for="preset-switcher" class='select'> {{ $t('settings.presets') }}
<select id="preset-switcher" v-model="selected" class="preset-switcher"> <label
<option v-for="style in availableStyles" for="preset-switcher"
:value="style" class="select"
:style="{ >
backgroundColor: style[1] || style.theme.colors.bg, <select
color: style[3] || style.theme.colors.text id="preset-switcher"
}"> v-model="selected"
{{style[0] || style.name}} class="preset-switcher"
</option> >
</select> <option
<i class="icon-down-open"/> v-for="style in availableStyles"
</label> :value="style"
</div> :style="{
</template> backgroundColor: style[1] || style.theme.colors.bg,
</export-import> color: style[3] || style.theme.colors.text
}"
>
{{ style[0] || style.name }}
</option>
</select>
<i class="icon-down-open" />
</label>
</div>
</template>
</export-import>
</div>
<div class="save-load-options">
<span class="keep-option">
<input
id="keep-color"
v-model="keepColor"
type="checkbox"
>
<label for="keep-color">{{ $t('settings.style.switcher.keep_color') }}</label>
</span>
<span class="keep-option">
<input
id="keep-shadows"
v-model="keepShadows"
type="checkbox"
>
<label for="keep-shadows">{{ $t('settings.style.switcher.keep_shadows') }}</label>
</span>
<span class="keep-option">
<input
id="keep-opacity"
v-model="keepOpacity"
type="checkbox"
>
<label for="keep-opacity">{{ $t('settings.style.switcher.keep_opacity') }}</label>
</span>
<span class="keep-option">
<input
id="keep-roundness"
v-model="keepRoundness"
type="checkbox"
>
<label for="keep-roundness">{{ $t('settings.style.switcher.keep_roundness') }}</label>
</span>
<span class="keep-option">
<input
id="keep-fonts"
v-model="keepFonts"
type="checkbox"
>
<label for="keep-fonts">{{ $t('settings.style.switcher.keep_fonts') }}</label>
</span>
<p>{{ $t('settings.style.switcher.save_load_hint') }}</p>
</div>
</div> </div>
<div class="save-load-options">
<span class="keep-option"> <div class="preview-container">
<input <preview :style="previewRules" />
id="keep-color" </div>
type="checkbox"
v-model="keepColor"> <keep-alive>
<label for="keep-color">{{$t('settings.style.switcher.keep_color')}}</label> <tab-switcher key="style-tweak">
</span> <div
<span class="keep-option"> :label="$t('settings.style.common_colors._tab_label')"
<input class="color-container"
id="keep-shadows" >
type="checkbox" <div class="tab-header">
v-model="keepShadows"> <p>{{ $t('settings.theme_help') }}</p>
<label for="keep-shadows">{{$t('settings.style.switcher.keep_shadows')}}</label> <button
</span> class="btn"
<span class="keep-option"> @click="clearOpacity"
<input >
id="keep-opacity" {{ $t('settings.style.switcher.clear_opacity') }}
type="checkbox" </button>
v-model="keepOpacity"> <button
<label for="keep-opacity">{{$t('settings.style.switcher.keep_opacity')}}</label> class="btn"
</span> @click="clearV1"
<span class="keep-option"> >
<input {{ $t('settings.style.switcher.clear_all') }}
id="keep-roundness" </button>
type="checkbox" </div>
v-model="keepRoundness"> <p>{{ $t('settings.theme_help_v2_1') }}</p>
<label for="keep-roundness">{{$t('settings.style.switcher.keep_roundness')}}</label> <h4>{{ $t('settings.style.common_colors.main') }}</h4>
</span> <div class="color-item">
<span class="keep-option"> <ColorInput
<input v-model="bgColorLocal"
id="keep-fonts" name="bgColor"
type="checkbox" :label="$t('settings.background')"
v-model="keepFonts"> />
<label for="keep-fonts">{{$t('settings.style.switcher.keep_fonts')}}</label> <OpacityInput
</span> v-model="bgOpacityLocal"
<p>{{$t('settings.style.switcher.save_load_hint')}}</p> name="bgOpacity"
:fallback="previewTheme.opacity.bg || 1"
/>
<ColorInput
v-model="textColorLocal"
name="textColor"
:label="$t('settings.text')"
/>
<ContrastRatio :contrast="previewContrast.bgText" />
<ColorInput
v-model="linkColorLocal"
name="linkColor"
:label="$t('settings.links')"
/>
<ContrastRatio :contrast="previewContrast.bgLink" />
</div>
<div class="color-item">
<ColorInput
v-model="fgColorLocal"
name="fgColor"
:label="$t('settings.foreground')"
/>
<ColorInput
v-model="fgTextColorLocal"
name="fgTextColor"
:label="$t('settings.text')"
:fallback="previewTheme.colors.fgText"
/>
<ColorInput
v-model="fgLinkColorLocal"
name="fgLinkColor"
:label="$t('settings.links')"
:fallback="previewTheme.colors.fgLink"
/>
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
</div>
<h4>{{ $t('settings.style.common_colors.rgbo') }}</h4>
<div class="color-item">
<ColorInput
v-model="cRedColorLocal"
name="cRedColor"
:label="$t('settings.cRed')"
/>
<ContrastRatio :contrast="previewContrast.bgRed" />
<ColorInput
v-model="cBlueColorLocal"
name="cBlueColor"
:label="$t('settings.cBlue')"
/>
<ContrastRatio :contrast="previewContrast.bgBlue" />
</div>
<div class="color-item">
<ColorInput
v-model="cGreenColorLocal"
name="cGreenColor"
:label="$t('settings.cGreen')"
/>
<ContrastRatio :contrast="previewContrast.bgGreen" />
<ColorInput
v-model="cOrangeColorLocal"
name="cOrangeColor"
:label="$t('settings.cOrange')"
/>
<ContrastRatio :contrast="previewContrast.bgOrange" />
</div>
<p>{{ $t('settings.theme_help_v2_2') }}</p>
</div>
<div
:label="$t('settings.style.advanced_colors._tab_label')"
class="color-container"
>
<div class="tab-header">
<p>{{ $t('settings.theme_help') }}</p>
<button
class="btn"
@click="clearOpacity"
>
{{ $t('settings.style.switcher.clear_opacity') }}
</button>
<button
class="btn"
@click="clearV1"
>
{{ $t('settings.style.switcher.clear_all') }}
</button>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
<ColorInput
v-model="alertErrorColorLocal"
name="alertError"
:label="$t('settings.style.advanced_colors.alert_error')"
:fallback="previewTheme.colors.alertError"
/>
<ContrastRatio :contrast="previewContrast.alertError" />
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
<ColorInput
v-model="badgeNotificationColorLocal"
name="badgeNotification"
:label="$t('settings.style.advanced_colors.badge_notification')"
:fallback="previewTheme.colors.badgeNotification"
/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.panel_header') }}</h4>
<ColorInput
v-model="panelColorLocal"
name="panelColor"
:fallback="fgColorLocal"
:label="$t('settings.background')"
/>
<OpacityInput
v-model="panelOpacityLocal"
name="panelOpacity"
:fallback="previewTheme.opacity.panel || 1"
/>
<ColorInput
v-model="panelTextColorLocal"
name="panelTextColor"
:fallback="previewTheme.colors.panelText"
:label="$t('settings.text')"
/>
<ContrastRatio
:contrast="previewContrast.panelText"
large="1"
/>
<ColorInput
v-model="panelLinkColorLocal"
name="panelLinkColor"
:fallback="previewTheme.colors.panelLink"
:label="$t('settings.links')"
/>
<ContrastRatio
:contrast="previewContrast.panelLink"
large="1"
/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.top_bar') }}</h4>
<ColorInput
v-model="topBarColorLocal"
name="topBarColor"
:fallback="fgColorLocal"
:label="$t('settings.background')"
/>
<ColorInput
v-model="topBarTextColorLocal"
name="topBarTextColor"
:fallback="previewTheme.colors.topBarText"
:label="$t('settings.text')"
/>
<ContrastRatio :contrast="previewContrast.topBarText" />
<ColorInput
v-model="topBarLinkColorLocal"
name="topBarLinkColor"
:fallback="previewTheme.colors.topBarLink"
:label="$t('settings.links')"
/>
<ContrastRatio :contrast="previewContrast.topBarLink" />
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.inputs') }}</h4>
<ColorInput
v-model="inputColorLocal"
name="inputColor"
:fallback="fgColorLocal"
:label="$t('settings.background')"
/>
<OpacityInput
v-model="inputOpacityLocal"
name="inputOpacity"
:fallback="previewTheme.opacity.input || 1"
/>
<ColorInput
v-model="inputTextColorLocal"
name="inputTextColor"
:fallback="previewTheme.colors.inputText"
:label="$t('settings.text')"
/>
<ContrastRatio :contrast="previewContrast.inputText" />
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.buttons') }}</h4>
<ColorInput
v-model="btnColorLocal"
name="btnColor"
:fallback="fgColorLocal"
:label="$t('settings.background')"
/>
<OpacityInput
v-model="btnOpacityLocal"
name="btnOpacity"
:fallback="previewTheme.opacity.btn || 1"
/>
<ColorInput
v-model="btnTextColorLocal"
name="btnTextColor"
:fallback="previewTheme.colors.btnText"
:label="$t('settings.text')"
/>
<ContrastRatio :contrast="previewContrast.btnText" />
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.borders') }}</h4>
<ColorInput
v-model="borderColorLocal"
name="borderColor"
:fallback="previewTheme.colors.border"
:label="$t('settings.style.common.color')"
/>
<OpacityInput
v-model="borderOpacityLocal"
name="borderOpacity"
:fallback="previewTheme.opacity.border || 1"
/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.faint_text') }}</h4>
<ColorInput
v-model="faintColorLocal"
name="faintColor"
:fallback="previewTheme.colors.faint || 1"
:label="$t('settings.text')"
/>
<ColorInput
v-model="faintLinkColorLocal"
name="faintLinkColor"
:fallback="previewTheme.colors.faintLink"
:label="$t('settings.links')"
/>
<ColorInput
v-model="panelFaintColorLocal"
name="panelFaintColor"
:fallback="previewTheme.colors.panelFaint"
:label="$t('settings.style.advanced_colors.panel_header')"
/>
<OpacityInput
v-model="faintOpacityLocal"
name="faintOpacity"
:fallback="previewTheme.opacity.faint || 0.5"
/>
</div>
</div>
<div
:label="$t('settings.style.radii._tab_label')"
class="radius-container"
>
<div class="tab-header">
<p>{{ $t('settings.radii_help') }}</p>
<button
class="btn"
@click="clearRoundness"
>
{{ $t('settings.style.switcher.clear_all') }}
</button>
</div>
<RangeInput
v-model="btnRadiusLocal"
name="btnRadius"
:label="$t('settings.btnRadius')"
:fallback="previewTheme.radii.btn"
max="16"
hard-min="0"
/>
<RangeInput
v-model="inputRadiusLocal"
name="inputRadius"
:label="$t('settings.inputRadius')"
:fallback="previewTheme.radii.input"
max="9"
hard-min="0"
/>
<RangeInput
v-model="checkboxRadiusLocal"
name="checkboxRadius"
:label="$t('settings.checkboxRadius')"
:fallback="previewTheme.radii.checkbox"
max="16"
hard-min="0"
/>
<RangeInput
v-model="panelRadiusLocal"
name="panelRadius"
:label="$t('settings.panelRadius')"
:fallback="previewTheme.radii.panel"
max="50"
hard-min="0"
/>
<RangeInput
v-model="avatarRadiusLocal"
name="avatarRadius"
:label="$t('settings.avatarRadius')"
:fallback="previewTheme.radii.avatar"
max="28"
hard-min="0"
/>
<RangeInput
v-model="avatarAltRadiusLocal"
name="avatarAltRadius"
:label="$t('settings.avatarAltRadius')"
:fallback="previewTheme.radii.avatarAlt"
max="28"
hard-min="0"
/>
<RangeInput
v-model="attachmentRadiusLocal"
name="attachmentRadius"
:label="$t('settings.attachmentRadius')"
:fallback="previewTheme.radii.attachment"
max="50"
hard-min="0"
/>
<RangeInput
v-model="tooltipRadiusLocal"
name="tooltipRadius"
:label="$t('settings.tooltipRadius')"
:fallback="previewTheme.radii.tooltip"
max="50"
hard-min="0"
/>
</div>
<div
:label="$t('settings.style.shadows._tab_label')"
class="shadow-container"
>
<div class="tab-header shadow-selector">
<div class="select-container">
{{ $t('settings.style.shadows.component') }}
<label
for="shadow-switcher"
class="select"
>
<select
id="shadow-switcher"
v-model="shadowSelected"
class="shadow-switcher"
>
<option
v-for="shadow in shadowsAvailable"
:value="shadow"
>
{{ $t('settings.style.shadows.components.' + shadow) }}
</option>
</select>
<i class="icon-down-open" />
</label>
</div>
<div class="override">
<label
for="override"
class="label"
>
{{ $t('settings.style.shadows.override') }}
</label>
<input
id="override"
v-model="currentShadowOverriden"
name="override"
class="input-override"
type="checkbox"
>
<label
class="checkbox-label"
for="override"
/>
</div>
<button
class="btn"
@click="clearShadows"
>
{{ $t('settings.style.switcher.clear_all') }}
</button>
</div>
<shadow-control
v-model="currentShadow"
:ready="!!currentShadowFallback"
:fallback="currentShadowFallback"
/>
<div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
<i18n
path="settings.style.shadows.filter_hint.always_drop_shadow"
tag="p"
>
<code>filter: drop-shadow()</code>
</i18n>
<p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
<i18n
path="settings.style.shadows.filter_hint.drop_shadow_syntax"
tag="p"
>
<code>drop-shadow</code>
<code>spread-radius</code>
<code>inset</code>
</i18n>
<i18n
path="settings.style.shadows.filter_hint.inset_classic"
tag="p"
>
<code>box-shadow</code>
</i18n>
<p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p>
</div>
</div>
<div
:label="$t('settings.style.fonts._tab_label')"
class="fonts-container"
>
<div class="tab-header">
<p>{{ $t('settings.style.fonts.help') }}</p>
<button
class="btn"
@click="clearFonts"
>
{{ $t('settings.style.switcher.clear_all') }}
</button>
</div>
<FontControl
v-model="fontsLocal.interface"
name="ui"
:label="$t('settings.style.fonts.components.interface')"
:fallback="previewTheme.fonts.interface"
no-inherit="1"
/>
<FontControl
v-model="fontsLocal.input"
name="input"
:label="$t('settings.style.fonts.components.input')"
:fallback="previewTheme.fonts.input"
/>
<FontControl
v-model="fontsLocal.post"
name="post"
:label="$t('settings.style.fonts.components.post')"
:fallback="previewTheme.fonts.post"
/>
<FontControl
v-model="fontsLocal.postCode"
name="postCode"
:label="$t('settings.style.fonts.components.postCode')"
:fallback="previewTheme.fonts.postCode"
/>
</div>
</tab-switcher>
</keep-alive>
<div class="apply-container">
<button
class="btn submit"
:disabled="!themeValid"
@click="setCustomTheme"
>
{{ $t('general.apply') }}
</button>
<button
class="btn"
@click="clearAll"
>
{{ $t('settings.style.switcher.reset') }}
</button>
</div> </div>
</div> </div>
<div class="preview-container">
<preview :style="previewRules"/>
</div>
<keep-alive>
<tab-switcher key="style-tweak">
<div :label="$t('settings.style.common_colors._tab_label')" class="color-container">
<div class="tab-header">
<p>{{$t('settings.theme_help')}}</p>
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
</div>
<p>{{$t('settings.theme_help_v2_1')}}</p>
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
<div class="color-item">
<ColorInput name="bgColor" v-model="bgColorLocal" :label="$t('settings.background')"/>
<OpacityInput name="bgOpacity" v-model="bgOpacityLocal" :fallback="previewTheme.opacity.bg || 1"/>
<ColorInput name="textColor" v-model="textColorLocal" :label="$t('settings.text')"/>
<ContrastRatio :contrast="previewContrast.bgText"/>
<ColorInput name="linkColor" v-model="linkColorLocal" :label="$t('settings.links')"/>
<ContrastRatio :contrast="previewContrast.bgLink"/>
</div>
<div class="color-item">
<ColorInput name="fgColor" v-model="fgColorLocal" :label="$t('settings.foreground')"/>
<ColorInput name="fgTextColor" v-model="fgTextColorLocal" :label="$t('settings.text')" :fallback="previewTheme.colors.fgText"/>
<ColorInput name="fgLinkColor" v-model="fgLinkColorLocal" :label="$t('settings.links')" :fallback="previewTheme.colors.fgLink"/>
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
</div>
<h4>{{ $t('settings.style.common_colors.rgbo') }}</h4>
<div class="color-item">
<ColorInput name="cRedColor" v-model="cRedColorLocal" :label="$t('settings.cRed')"/>
<ContrastRatio :contrast="previewContrast.bgRed"/>
<ColorInput name="cBlueColor" v-model="cBlueColorLocal" :label="$t('settings.cBlue')"/>
<ContrastRatio :contrast="previewContrast.bgBlue"/>
</div>
<div class="color-item">
<ColorInput name="cGreenColor" v-model="cGreenColorLocal" :label="$t('settings.cGreen')"/>
<ContrastRatio :contrast="previewContrast.bgGreen"/>
<ColorInput name="cOrangeColor" v-model="cOrangeColorLocal" :label="$t('settings.cOrange')"/>
<ContrastRatio :contrast="previewContrast.bgOrange"/>
</div>
<p>{{$t('settings.theme_help_v2_2')}}</p>
</div>
<div :label="$t('settings.style.advanced_colors._tab_label')" class="color-container">
<div class="tab-header">
<p>{{$t('settings.theme_help')}}</p>
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
<ColorInput name="alertError" v-model="alertErrorColorLocal" :label="$t('settings.style.advanced_colors.alert_error')" :fallback="previewTheme.colors.alertError"/>
<ContrastRatio :contrast="previewContrast.alertError"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
<ColorInput name="badgeNotification" v-model="badgeNotificationColorLocal" :label="$t('settings.style.advanced_colors.badge_notification')" :fallback="previewTheme.colors.badgeNotification"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.panel_header') }}</h4>
<ColorInput name="panelColor" v-model="panelColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
<OpacityInput name="panelOpacity" v-model="panelOpacityLocal" :fallback="previewTheme.opacity.panel || 1"/>
<ColorInput name="panelTextColor" v-model="panelTextColorLocal" :fallback="previewTheme.colors.panelText" :label="$t('settings.text')"/>
<ContrastRatio :contrast="previewContrast.panelText" large="1"/>
<ColorInput name="panelLinkColor" v-model="panelLinkColorLocal" :fallback="previewTheme.colors.panelLink" :label="$t('settings.links')"/>
<ContrastRatio :contrast="previewContrast.panelLink" large="1"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.top_bar') }}</h4>
<ColorInput name="topBarColor" v-model="topBarColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
<ColorInput name="topBarTextColor" v-model="topBarTextColorLocal" :fallback="previewTheme.colors.topBarText" :label="$t('settings.text')"/>
<ContrastRatio :contrast="previewContrast.topBarText"/>
<ColorInput name="topBarLinkColor" v-model="topBarLinkColorLocal" :fallback="previewTheme.colors.topBarLink" :label="$t('settings.links')"/>
<ContrastRatio :contrast="previewContrast.topBarLink"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.inputs') }}</h4>
<ColorInput name="inputColor" v-model="inputColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
<OpacityInput name="inputOpacity" v-model="inputOpacityLocal" :fallback="previewTheme.opacity.input || 1"/>
<ColorInput name="inputTextColor" v-model="inputTextColorLocal" :fallback="previewTheme.colors.inputText" :label="$t('settings.text')"/>
<ContrastRatio :contrast="previewContrast.inputText"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.buttons') }}</h4>
<ColorInput name="btnColor" v-model="btnColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
<OpacityInput name="btnOpacity" v-model="btnOpacityLocal" :fallback="previewTheme.opacity.btn || 1"/>
<ColorInput name="btnTextColor" v-model="btnTextColorLocal" :fallback="previewTheme.colors.btnText" :label="$t('settings.text')"/>
<ContrastRatio :contrast="previewContrast.btnText"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.borders') }}</h4>
<ColorInput name="borderColor" v-model="borderColorLocal" :fallback="previewTheme.colors.border" :label="$t('settings.style.common.color')"/>
<OpacityInput name="borderOpacity" v-model="borderOpacityLocal" :fallback="previewTheme.opacity.border || 1"/>
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.faint_text') }}</h4>
<ColorInput name="faintColor" v-model="faintColorLocal" :fallback="previewTheme.colors.faint || 1" :label="$t('settings.text')"/>
<ColorInput name="faintLinkColor" v-model="faintLinkColorLocal" :fallback="previewTheme.colors.faintLink" :label="$t('settings.links')"/>
<ColorInput name="panelFaintColor" v-model="panelFaintColorLocal" :fallback="previewTheme.colors.panelFaint" :label="$t('settings.style.advanced_colors.panel_header')"/>
<OpacityInput name="faintOpacity" v-model="faintOpacityLocal" :fallback="previewTheme.opacity.faint || 0.5"/>
</div>
</div>
<div :label="$t('settings.style.radii._tab_label')" class="radius-container">
<div class="tab-header">
<p>{{$t('settings.radii_help')}}</p>
<button class="btn" @click="clearRoundness">{{$t('settings.style.switcher.clear_all')}}</button>
</div>
<RangeInput name="btnRadius" :label="$t('settings.btnRadius')" v-model="btnRadiusLocal" :fallback="previewTheme.radii.btn" max="16" hardMin="0"/>
<RangeInput name="inputRadius" :label="$t('settings.inputRadius')" v-model="inputRadiusLocal" :fallback="previewTheme.radii.input" max="9" hardMin="0"/>
<RangeInput name="checkboxRadius" :label="$t('settings.checkboxRadius')" v-model="checkboxRadiusLocal" :fallback="previewTheme.radii.checkbox" max="16" hardMin="0"/>
<RangeInput name="panelRadius" :label="$t('settings.panelRadius')" v-model="panelRadiusLocal" :fallback="previewTheme.radii.panel" max="50" hardMin="0"/>
<RangeInput name="avatarRadius" :label="$t('settings.avatarRadius')" v-model="avatarRadiusLocal" :fallback="previewTheme.radii.avatar" max="28" hardMin="0"/>
<RangeInput name="avatarAltRadius" :label="$t('settings.avatarAltRadius')" v-model="avatarAltRadiusLocal" :fallback="previewTheme.radii.avatarAlt" max="28" hardMin="0"/>
<RangeInput name="attachmentRadius" :label="$t('settings.attachmentRadius')" v-model="attachmentRadiusLocal" :fallback="previewTheme.radii.attachment" max="50" hardMin="0"/>
<RangeInput name="tooltipRadius" :label="$t('settings.tooltipRadius')" v-model="tooltipRadiusLocal" :fallback="previewTheme.radii.tooltip" max="50" hardMin="0"/>
</div>
<div :label="$t('settings.style.shadows._tab_label')" class="shadow-container">
<div class="tab-header shadow-selector">
<div class="select-container">
{{$t('settings.style.shadows.component')}}
<label for="shadow-switcher" class="select">
<select id="shadow-switcher" v-model="shadowSelected" class="shadow-switcher">
<option v-for="shadow in shadowsAvailable"
:value="shadow">
{{$t('settings.style.shadows.components.' + shadow)}}
</option>
</select>
<i class="icon-down-open"/>
</label>
</div>
<div class="override">
<label for="override" class="label">
{{$t('settings.style.shadows.override')}}
</label>
<input
v-model="currentShadowOverriden"
name="override"
id="override"
class="input-override"
type="checkbox">
<label class="checkbox-label" for="override"></label>
</div>
<button class="btn" @click="clearShadows">{{$t('settings.style.switcher.clear_all')}}</button>
</div>
<shadow-control :ready="!!currentShadowFallback" :fallback="currentShadowFallback" v-model="currentShadow"/>
<div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
<i18n path="settings.style.shadows.filter_hint.always_drop_shadow" tag="p">
<code>filter: drop-shadow()</code>
</i18n>
<p>{{$t('settings.style.shadows.filter_hint.avatar_inset')}}</p>
<i18n path="settings.style.shadows.filter_hint.drop_shadow_syntax" tag="p">
<code>drop-shadow</code>
<code>spread-radius</code>
<code>inset</code>
</i18n>
<i18n path="settings.style.shadows.filter_hint.inset_classic" tag="p">
<code>box-shadow</code>
</i18n>
<p>{{$t('settings.style.shadows.filter_hint.spread_zero')}}</p>
</div>
</div>
<div :label="$t('settings.style.fonts._tab_label')" class="fonts-container">
<div class="tab-header">
<p>{{$t('settings.style.fonts.help')}}</p>
<button class="btn" @click="clearFonts">{{$t('settings.style.switcher.clear_all')}}</button>
</div>
<FontControl
name="ui"
v-model="fontsLocal.interface"
:label="$t('settings.style.fonts.components.interface')"
:fallback="previewTheme.fonts.interface"
no-inherit="1"/>
<FontControl
name="input"
v-model="fontsLocal.input"
:label="$t('settings.style.fonts.components.input')"
:fallback="previewTheme.fonts.input"/>
<FontControl
name="post"
v-model="fontsLocal.post"
:label="$t('settings.style.fonts.components.post')"
:fallback="previewTheme.fonts.post"/>
<FontControl
name="postCode"
v-model="fontsLocal.postCode"
:label="$t('settings.style.fonts.components.postCode')"
:fallback="previewTheme.fonts.postCode"/>
</div>
</tab-switcher>
</keep-alive>
<div class="apply-container">
<button class="btn submit" :disabled="!themeValid" @click="setCustomTheme">{{$t('general.apply')}}</button>
<button class="btn" @click="clearAll">{{$t('settings.style.switcher.reset')}}</button>
</div>
</div>
</template> </template>
<script src="./style_switcher.js"></script> <script src="./style_switcher.js"></script>

View file

@ -1,5 +1,10 @@
<template> <template>
<Timeline :title="tag" :timeline="timeline" :timeline-name="'tag'" :tag="tag" /> <Timeline
:title="tag"
:timeline="timeline"
:timeline-name="'tag'"
:tag="tag"
/>
</template> </template>
<script src='./tag_timeline.js'></script> <script src='./tag_timeline.js'></script>

View file

@ -2,8 +2,10 @@
<div> <div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body"> <div class="panel-body">
<div v-html="content" class="tos-content"> <div
</div> class="tos-content"
v-html="content"
/>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,8 @@
<template> <template>
<time :datetime="time" :title="localeDateString"> <time
:datetime="time"
:title="localeDateString"
>
{{ $t(relativeTime.key, [relativeTime.num]) }} {{ $t(relativeTime.key, [relativeTime.num]) }}
</time> </time>
</template> </template>
@ -16,12 +19,6 @@ export default {
interval: null interval: null
} }
}, },
created () {
this.refreshRelativeTimeObject()
},
destroyed () {
clearTimeout(this.interval)
},
computed: { computed: {
localeDateString () { localeDateString () {
return typeof this.time === 'string' return typeof this.time === 'string'
@ -29,6 +26,12 @@ export default {
: this.time.toLocaleString() : this.time.toLocaleString()
} }
}, },
created () {
this.refreshRelativeTimeObject()
},
destroyed () {
clearTimeout(this.interval)
},
methods: { methods: {
refreshRelativeTimeObject () { refreshRelativeTimeObject () {
const nowThreshold = typeof this.nowThreshold === 'number' ? this.nowThreshold : 1 const nowThreshold = typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
@ -45,4 +48,4 @@ export default {
} }
} }
} }
</script> </script>

View file

@ -2,41 +2,66 @@
<div :class="classes.root"> <div :class="classes.root">
<div :class="classes.header"> <div :class="classes.header">
<div class="title"> <div class="title">
{{title}} {{ title }}
</div> </div>
<div @click.prevent class="loadmore-error alert error" v-if="timelineError"> <div
{{$t('timeline.error_fetching')}} v-if="timelineError"
class="loadmore-error alert error"
@click.prevent
>
{{ $t('timeline.error_fetching') }}
</div> </div>
<button @click.prevent="showNewStatuses" class="loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError"> <button
{{$t('timeline.show_new')}}{{newStatusCountStr}} v-if="timeline.newStatusCount > 0 && !timelineError"
class="loadmore-button"
@click.prevent="showNewStatuses"
>
{{ $t('timeline.show_new') }}{{ newStatusCountStr }}
</button> </button>
<div @click.prevent class="loadmore-text faint" v-if="!timeline.newStatusCount > 0 && !timelineError"> <div
{{$t('timeline.up_to_date')}} v-if="!timeline.newStatusCount > 0 && !timelineError"
class="loadmore-text faint"
@click.prevent
>
{{ $t('timeline.up_to_date') }}
</div> </div>
</div> </div>
<div :class="classes.body"> <div :class="classes.body">
<div class="timeline"> <div class="timeline">
<conversation <conversation
v-for="status in timeline.visibleStatuses" v-for="status in timeline.visibleStatuses"
class="status-fadein"
:key="status.id" :key="status.id"
class="status-fadein"
:statusoid="status" :statusoid="status"
:collapsable="true" :collapsable="true"
/> />
</div> </div>
</div> </div>
<div :class="classes.footer"> <div :class="classes.footer">
<div v-if="count===0" class="new-status-notification text-center panel-footer faint"> <div
{{$t('timeline.no_statuses')}} v-if="count===0"
class="new-status-notification text-center panel-footer faint"
>
{{ $t('timeline.no_statuses') }}
</div> </div>
<div v-else-if="bottomedOut" class="new-status-notification text-center panel-footer faint"> <div
{{$t('timeline.no_more_statuses')}} v-else-if="bottomedOut"
class="new-status-notification text-center panel-footer faint"
>
{{ $t('timeline.no_more_statuses') }}
</div> </div>
<a v-else-if="!timeline.loading" href="#" v-on:click.prevent='fetchOlderStatuses()'> <a
<div class="new-status-notification text-center panel-footer">{{$t('timeline.load_older')}}</div> v-else-if="!timeline.loading"
href="#"
@click.prevent="fetchOlderStatuses()"
>
<div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
</a> </a>
<div v-else class="new-status-notification text-center panel-footer"> <div
<i class="icon-spin3 animate-spin"/> v-else
class="new-status-notification text-center panel-footer"
>
<i class="icon-spin3 animate-spin" />
</div> </div>
</div> </div>
</div> </div>

View file

@ -5,7 +5,7 @@
:title="user.screen_name" :title="user.screen_name"
:src="user.profile_image_url_original" :src="user.profile_image_url_original"
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }" :class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
:imageLoadError="imageLoadError" :image-load-error="imageLoadError"
/> />
</template> </template>

View file

@ -1,134 +1,256 @@
<template> <template>
<div class="user-card" :class="classes" :style="style"> <div
<div class="panel-heading"> class="user-card"
<div class='user-info'> :class="classes"
<div class='container'> :style="style"
<router-link :to="userProfileLink(user)"> >
<UserAvatar :betterShadow="betterShadow" :user="user"/> <div class="panel-heading">
</router-link> <div class="user-info">
<div class="user-summary"> <div class="container">
<div class="top-line"> <router-link :to="userProfileLink(user)">
<div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div> <UserAvatar
<div :title="user.name" class='user-name' v-else>{{user.name}}</div> :better-shadow="betterShadow"
<router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser"> :user="user"
<i class="button-icon icon-wrench usersettings" :title="$t('tool_tip.user_settings')"></i> />
</router-link> </router-link>
<a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local"> <div class="user-summary">
<i class="icon-link-ext usersettings"></i> <div class="top-line">
</a> <div
</div> v-if="user.name_html"
:title="user.name"
class="user-name"
v-html="user.name_html"
/>
<div
v-else
:title="user.name"
class="user-name"
>
{{ user.name }}
</div>
<router-link
v-if="!isOtherUser"
:to="{ name: 'user-settings' }"
>
<i
class="button-icon icon-wrench usersettings"
:title="$t('tool_tip.user_settings')"
/>
</router-link>
<a
v-if="isOtherUser && !user.is_local"
:href="user.statusnet_profile_url"
target="_blank"
>
<i class="icon-link-ext usersettings" />
</a>
</div>
<div class="bottom-line"> <div class="bottom-line">
<router-link class="user-screen-name" :to="userProfileLink(user)">@{{user.screen_name}}</router-link> <router-link
<span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span> class="user-screen-name"
<span v-if="user.locked"><i class="icon icon-lock"></i></span> :to="userProfileLink(user)"
<span v-if="!hideUserStatsLocal && !hideBio" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span> >
@{{ user.screen_name }}
</router-link>
<span
v-if="!hideBio && !!visibleRole"
class="alert staff"
>{{ visibleRole }}</span>
<span v-if="user.locked"><i class="icon icon-lock" /></span>
<span
v-if="!hideUserStatsLocal && !hideBio"
class="dailyAvg"
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
</div>
</div> </div>
</div> </div>
</div> <div class="user-meta">
<div class="user-meta"> <div
<div v-if="user.follows_you && loggedIn && isOtherUser" class="following"> v-if="user.follows_you && loggedIn && isOtherUser"
{{ $t('user_card.follows_you') }} class="following"
>
{{ $t('user_card.follows_you') }}
</div>
<div
v-if="isOtherUser && (loggedIn || !switcher)"
class="highlighter"
>
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
<input
v-if="userHighlightType !== 'disabled'"
:id="'userHighlightColorTx'+user.id"
v-model="userHighlightColor"
class="userHighlightText"
type="text"
>
<input
v-if="userHighlightType !== 'disabled'"
:id="'userHighlightColor'+user.id"
v-model="userHighlightColor"
class="userHighlightCl"
type="color"
>
<label
for="style-switcher"
class="userHighlightSel select"
>
<select
:id="'userHighlightSel'+user.id"
v-model="userHighlightType"
class="userHighlightSel"
>
<option value="disabled">No highlight</option>
<option value="solid">Solid bg</option>
<option value="striped">Striped bg</option>
<option value="side">Side stripe</option>
</select>
<i class="icon-down-open" />
</label>
</div>
</div> </div>
<div class="highlighter" v-if="isOtherUser && (loggedIn || !switcher)"> <div
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to --> v-if="isOtherUser"
<input class="userHighlightText" type="text" :id="'userHighlightColorTx'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/> class="user-interactions"
<input class="userHighlightCl" type="color" :id="'userHighlightColor'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/> >
<label for="style-switcher" class='userHighlightSel select'> <div
<select class="userHighlightSel" :id="'userHighlightSel'+user.id" v-model="userHighlightType"> v-if="loggedIn"
<option value="disabled">No highlight</option> class="follow"
<option value="solid">Solid bg</option> >
<option value="striped">Striped bg</option> <span v-if="user.following">
<option value="side">Side stripe</option> <!--Following them!-->
</select> <button
<i class="icon-down-open"/> class="pressed"
</label> :disabled="followRequestInProgress"
:title="$t('user_card.follow_unfollow')"
@click="unfollowUser"
>
<template v-if="followRequestInProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else>
{{ $t('user_card.following') }}
</template>
</button>
</span>
<span v-if="!user.following">
<button
:disabled="followRequestInProgress"
:title="followRequestSent ? $t('user_card.follow_again') : ''"
@click="followUser"
>
<template v-if="followRequestInProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else-if="followRequestSent">
{{ $t('user_card.follow_sent') }}
</template>
<template v-else>
{{ $t('user_card.follow') }}
</template>
</button>
</span>
</div>
<div
v-if="isOtherUser && loggedIn"
class="mute"
>
<span v-if="user.muted">
<button
class="pressed"
@click="unmuteUser"
>
{{ $t('user_card.muted') }}
</button>
</span>
<span v-if="!user.muted">
<button @click="muteUser">
{{ $t('user_card.mute') }}
</button>
</span>
</div>
<div v-if="!loggedIn && user.is_local">
<RemoteFollow :user="user" />
</div>
<div
v-if="isOtherUser && loggedIn"
class="block"
>
<span v-if="user.statusnet_blocking">
<button
class="pressed"
@click="unblockUser"
>
{{ $t('user_card.blocked') }}
</button>
</span>
<span v-if="!user.statusnet_blocking">
<button @click="blockUser">
{{ $t('user_card.block') }}
</button>
</span>
</div>
<div
v-if="isOtherUser && loggedIn"
class="block"
>
<span>
<button @click="reportUser">
{{ $t('user_card.report') }}
</button>
</span>
</div>
<ModerationTools
v-if="loggedIn.role === &quot;admin&quot;"
:user="user"
/>
</div> </div>
</div> </div>
<div v-if="isOtherUser" class="user-interactions">
<div class="follow" v-if="loggedIn">
<span v-if="user.following">
<!--Following them!-->
<button @click="unfollowUser" class="pressed" :disabled="followRequestInProgress" :title="$t('user_card.follow_unfollow')">
<template v-if="followRequestInProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else>
{{ $t('user_card.following') }}
</template>
</button>
</span>
<span v-if="!user.following">
<button @click="followUser" :disabled="followRequestInProgress" :title="followRequestSent ? $t('user_card.follow_again') : ''">
<template v-if="followRequestInProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else-if="followRequestSent">
{{ $t('user_card.follow_sent') }}
</template>
<template v-else>
{{ $t('user_card.follow') }}
</template>
</button>
</span>
</div>
<div class='mute' v-if='isOtherUser && loggedIn'>
<span v-if='user.muted'>
<button @click="unmuteUser" class="pressed">
{{ $t('user_card.muted') }}
</button>
</span>
<span v-if='!user.muted'>
<button @click="muteUser">
{{ $t('user_card.mute') }}
</button>
</span>
</div>
<div v-if='!loggedIn && user.is_local'>
<RemoteFollow :user="user" />
</div>
<div class='block' v-if='isOtherUser && loggedIn'>
<span v-if='user.statusnet_blocking'>
<button @click="unblockUser" class="pressed">
{{ $t('user_card.blocked') }}
</button>
</span>
<span v-if='!user.statusnet_blocking'>
<button @click="blockUser">
{{ $t('user_card.block') }}
</button>
</span>
</div>
<div class='block' v-if='isOtherUser && loggedIn'>
<span>
<button @click="reportUser">
{{ $t('user_card.report') }}
</button>
</span>
</div>
<ModerationTools :user='user' v-if='loggedIn.role === "admin"'/>
</div>
</div> </div>
</div> <div
<div class="panel-body" v-if="!hideBio"> v-if="!hideBio"
<div v-if="!hideUserStatsLocal && switcher" class="user-counts"> class="panel-body"
<div class="user-count" v-on:click.prevent="setProfileView('statuses')"> >
<h5>{{ $t('user_card.statuses') }}</h5> <div
<span>{{user.statuses_count}} <br></span> v-if="!hideUserStatsLocal && switcher"
</div> class="user-counts"
<div class="user-count" v-on:click.prevent="setProfileView('friends')"> >
<h5>{{ $t('user_card.followees') }}</h5> <div
<span>{{user.friends_count}}</span> class="user-count"
</div> @click.prevent="setProfileView('statuses')"
<div class="user-count" v-on:click.prevent="setProfileView('followers')"> >
<h5>{{ $t('user_card.followers') }}</h5> <h5>{{ $t('user_card.statuses') }}</h5>
<span>{{user.followers_count}}</span> <span>{{ user.statuses_count }} <br></span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('friends')"
>
<h5>{{ $t('user_card.followees') }}</h5>
<span>{{ user.friends_count }}</span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('followers')"
>
<h5>{{ $t('user_card.followers') }}</h5>
<span>{{ user.followers_count }}</span>
</div>
</div> </div>
<p
v-if="!hideBio && user.description_html"
class="user-card-bio"
@click.prevent="linkClicked"
v-html="user.description_html"
/>
<p
v-else-if="!hideBio"
class="user-card-bio"
>
{{ user.description }}
</p>
</div> </div>
<p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="user-card-bio" v-html="user.description_html"></p>
<p v-else-if="!hideBio" class="user-card-bio">{{ user.description }}</p>
</div> </div>
</div>
</template> </template>
<script src="./user_card.js"></script> <script src="./user_card.js"></script>

View file

@ -1,14 +1,38 @@
<template> <template>
<div> <div>
<div class="user-finder-container"> <div class="user-finder-container">
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" /> <i
<a href="#" v-if="hidden" :title="$t('finder.find_user')"><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden" /></a> v-if="loading"
class="icon-spin4 user-finder-icon animate-spin-slow"
/>
<a
v-if="hidden"
href="#"
:title="$t('finder.find_user')"
><i
class="icon-user-plus user-finder-icon"
@click.prevent.stop="toggleHidden"
/></a>
<template v-else> <template v-else>
<input class="user-finder-input" ref="userSearchInput" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/> <input
<button class="btn search-button" @click="findUser(username)"> id="user-finder-input"
<i class="icon-search"/> ref="userSearchInput"
v-model="username"
class="user-finder-input"
:placeholder="$t('finder.find_user')"
type="text"
@keyup.enter="findUser(username)"
>
<button
class="btn search-button"
@click="findUser(username)"
>
<i class="icon-search" />
</button> </button>
<i class="button-icon icon-cancel user-finder-icon" @click.prevent.stop="toggleHidden"/> <i
class="button-icon icon-cancel user-finder-icon"
@click.prevent.stop="toggleHidden"
/>
</template> </template>
</div> </div>
</div> </div>
@ -25,7 +49,6 @@
align-items: baseline; align-items: baseline;
vertical-align: baseline; vertical-align: baseline;
.user-finder-input, .user-finder-input,
.search-button { .search-button {
height: 29px; height: 29px;

View file

@ -1,13 +1,23 @@
<template> <template>
<div class="user-panel"> <div class="user-panel">
<div
<div v-if="signedIn" key="user-panel" class="panel panel-default signed-in"> v-if="signedIn"
<UserCard :user="user" :hideBio="true" rounded="top"/> key="user-panel"
class="panel panel-default signed-in"
>
<UserCard
:user="user"
:hide-bio="true"
rounded="top"
/>
<div class="panel-footer"> <div class="panel-footer">
<post-status-form v-if='user'></post-status-form> <post-status-form v-if="user" />
</div> </div>
</div> </div>
<auth-form v-else key="user-panel"/> <auth-form
v-else
key="user-panel"
/>
</div> </div>
</template> </template>

View file

@ -1,75 +1,110 @@
<template> <template>
<div> <div>
<div v-if="user" class="user-profile panel panel-default"> <div
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/> v-if="user"
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher"> class="user-profile panel panel-default"
<div :label="$t('user_card.statuses')"> >
<div class="timeline"> <UserCard
<template v-for="statusId in user.pinnedStatuseIds"> :user="user"
<Conversation :switcher="true"
v-if="timeline.statusesObject[statusId]" :selected="timeline.viewing"
class="status-fadein" rounded="top"
:key="statusId" />
:statusoid="timeline.statusesObject[statusId]" <tab-switcher
:collapsable="true" ref="tabSwitcher"
:showPinned="true" :render-only-focused="true"
/> >
</template> <div :label="$t('user_card.statuses')">
<div class="timeline">
<template v-for="statusId in user.pinnedStatuseIds">
<Conversation
v-if="timeline.statusesObject[statusId]"
:key="statusId"
class="status-fadein"
:statusoid="timeline.statusesObject[statusId]"
:collapsable="true"
:show-pinned="true"
/>
</template>
</div>
<Timeline
:count="user.statuses_count"
:embedded="true"
:title="$t('user_profile.timeline_title')"
:timeline="timeline"
:timeline-name="'user'"
:user-id="userId"
/>
</div>
<div
v-if="followsTabVisible"
:label="$t('user_card.followees')"
:disabled="!user.friends_count"
>
<FriendList :user-id="userId">
<template
slot="item"
slot-scope="{item}"
>
<FollowCard :user="item" />
</template>
</FriendList>
</div>
<div
v-if="followersTabVisible"
:label="$t('user_card.followers')"
:disabled="!user.followers_count"
>
<FollowerList :user-id="userId">
<template
slot="item"
slot-scope="{item}"
>
<FollowCard
:user="item"
:no-follows-you="isUs"
/>
</template>
</FollowerList>
</div> </div>
<Timeline <Timeline
:count="user.statuses_count" :label="$t('user_card.media')"
:disabled="!media.visibleStatuses.length"
:embedded="true" :embedded="true"
:title="$t('user_profile.timeline_title')" :title="$t('user_card.media')"
:timeline="timeline" timeline-name="media"
:timeline-name="'user'" :timeline="media"
:user-id="userId" :user-id="userId"
/> />
<Timeline
v-if="isUs"
:label="$t('user_card.favorites')"
:disabled="!favorites.visibleStatuses.length"
:embedded="true"
:title="$t('user_card.favorites')"
timeline-name="favorites"
:timeline="favorites"
/>
</tab-switcher>
</div>
<div
v-else
class="panel user-profile-placeholder"
>
<div class="panel-heading">
<div class="title">
{{ $t('settings.profile_tab') }}
</div>
</div> </div>
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count"> <div class="panel-body">
<FriendList :userId="userId"> <span v-if="error">{{ error }}</span>
<template slot="item" slot-scope="{item}"> <i
<FollowCard :user="item" /> v-else
</template> class="icon-spin3 animate-spin"
</FriendList> />
</div>
<div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count">
<FollowerList :userId="userId">
<template slot="item" slot-scope="{item}">
<FollowCard :user="item" :noFollowsYou="isUs" />
</template>
</FollowerList>
</div>
<Timeline
:label="$t('user_card.media')"
:disabled="!media.visibleStatuses.length"
:embedded="true" :title="$t('user_card.media')"
timeline-name="media"
:timeline="media"
:user-id="userId"
/>
<Timeline
v-if="isUs"
:label="$t('user_card.favorites')"
:disabled="!favorites.visibleStatuses.length"
:embedded="true"
:title="$t('user_card.favorites')"
timeline-name="favorites"
:timeline="favorites"
/>
</tab-switcher>
</div>
<div v-else class="panel user-profile-placeholder">
<div class="panel-heading">
<div class="title">
{{ $t('settings.profile_tab') }}
</div> </div>
</div> </div>
<div class="panel-body">
<span v-if="error">{{ error }}</span>
<i class="icon-spin3 animate-spin" v-else></i>
</div>
</div> </div>
</div>
</template> </template>
<script src="./user_profile.js"></script> <script src="./user_profile.js"></script>

View file

@ -1,45 +1,75 @@
<template> <template>
<div class="modal-view" @click="closeModal" v-if="isOpen"> <div
<div class="user-reporting-panel panel" @click.stop=""> v-if="isOpen"
<div class="panel-heading"> class="modal-view"
<div class="title">{{$t('user_reporting.title', [user.screen_name])}}</div> @click="closeModal"
</div> >
<div class="panel-body"> <div
<div class="user-reporting-panel-left"> class="user-reporting-panel panel"
<div> @click.stop=""
<p>{{$t('user_reporting.add_comment_description')}}</p> >
<textarea <div class="panel-heading">
v-model="comment" <div class="title">
class="form-control" {{ $t('user_reporting.title', [user.screen_name]) }}
:placeholder="$t('user_reporting.additional_comments')"
rows="1"
@input="resize"
/>
</div>
<div v-if="!user.is_local">
<p>{{$t('user_reporting.forward_description')}}</p>
<Checkbox v-model="forward">{{$t('user_reporting.forward_to', [remoteInstance])}}</Checkbox>
</div>
<div>
<button class="btn btn-default" @click="reportUser" :disabled="processing">{{$t('user_reporting.submit')}}</button>
<div class="alert error" v-if="error">
{{$t('user_reporting.generic_error')}}
</div>
</div> </div>
</div> </div>
<div class="user-reporting-panel-right"> <div class="panel-body">
<List :items="statuses"> <div class="user-reporting-panel-left">
<template slot="item" slot-scope="{item}"> <div>
<div class="status-fadein user-reporting-panel-sitem"> <p>{{ $t('user_reporting.add_comment_description') }}</p>
<Status :inConversation="false" :focused="false" :statusoid="item" /> <textarea
<Checkbox :checked="isChecked(item.id)" @change="checked => toggleStatus(checked, item.id)" /> v-model="comment"
class="form-control"
:placeholder="$t('user_reporting.additional_comments')"
rows="1"
@input="resize"
/>
</div>
<div v-if="!user.is_local">
<p>{{ $t('user_reporting.forward_description') }}</p>
<Checkbox v-model="forward">
{{ $t('user_reporting.forward_to', [remoteInstance]) }}
</Checkbox>
</div>
<div>
<button
class="btn btn-default"
:disabled="processing"
@click="reportUser"
>
{{ $t('user_reporting.submit') }}
</button>
<div
v-if="error"
class="alert error"
>
{{ $t('user_reporting.generic_error') }}
</div> </div>
</template> </div>
</List> </div>
<div class="user-reporting-panel-right">
<List :items="statuses">
<template
slot="item"
slot-scope="{item}"
>
<div class="status-fadein user-reporting-panel-sitem">
<Status
:in-conversation="false"
:focused="false"
:statusoid="item"
/>
<Checkbox
:checked="isChecked(item.id)"
@change="checked => toggleStatus(checked, item.id)"
/>
</div>
</template>
</List>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script src="./user_reporting_modal.js"></script> <script src="./user_reporting_modal.js"></script>

View file

@ -1,19 +1,39 @@
<template> <template>
<div class="user-search panel panel-default"> <div class="user-search panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{$t('nav.user_search')}} {{ $t('nav.user_search') }}
</div> </div>
<div class="user-search-input-container"> <div class="user-search-input-container">
<input class="user-finder-input" ref="userSearchInput" @keyup.enter="newQuery(username)" v-model="username" :placeholder="$t('finder.find_user')"/> <input
<button class="btn search-button" @click="newQuery(username)"> ref="userSearchInput"
<i class="icon-search"/> v-model="username"
class="user-finder-input"
:placeholder="$t('finder.find_user')"
@keyup.enter="newQuery(username)"
>
<button
class="btn search-button"
@click="newQuery(username)"
>
<i class="icon-search" />
</button> </button>
</div> </div>
<div v-if="loading" class="text-center loading-icon"> <div
<i class="icon-spin3 animate-spin"/> v-if="loading"
class="text-center loading-icon"
>
<i class="icon-spin3 animate-spin" />
</div> </div>
<div v-else class="panel-body"> <div
<FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/> v-else
class="panel-body"
>
<FollowCard
v-for="user in users"
:key="user.id"
:user="user"
class="list-item"
/>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,13 +1,21 @@
<template> <template>
<div> <div>
<slot></slot> <slot />
<button class="btn btn-default" @click="confirm" :disabled="disabled"> <button
{{$t('general.confirm')}} class="btn btn-default"
</button> :disabled="disabled"
<button class="btn btn-default" @click="cancel" :disabled="disabled"> @click="confirm"
{{$t('general.cancel')}} >
</button> {{ $t('general.confirm') }}
</div> </button>
<button
class="btn btn-default"
:disabled="disabled"
@click="cancel"
>
{{ $t('general.cancel') }}
</button>
</div>
</template> </template>
<script src="./confirm.js"> <script src="./confirm.js">

View file

@ -1,86 +1,138 @@
<template> <template>
<div class="setting-item mfa-settings" v-if="readyInit && settings.available"> <div
v-if="readyInit && settings.available"
<div class="mfa-heading"> class="setting-item mfa-settings"
<h2>{{$t('settings.mfa.title')}}</h2> >
</div> <div class="mfa-heading">
<h2>{{ $t('settings.mfa.title') }}</h2>
<div>
<div class="setting-item" v-if="!setupInProgress">
<!-- Enabled methods -->
<h3>{{$t('settings.mfa.authentication_methods')}}</h3>
<totp-item :settings="settings" @deactivate="fetchSettings" @activate="activateOTP"/>
<br />
<div v-if="settings.enabled"> <!-- backup codes block-->
<recovery-codes :backup-codes="backupCodes" v-if="!confirmNewBackupCodes" />
<button class="btn btn-default" @click="getBackupCodes" v-if="!confirmNewBackupCodes">
{{$t('settings.mfa.generate_new_recovery_codes')}}
</button>
<div v-if="confirmNewBackupCodes">
<confirm @confirm="confirmBackupCodes" @cancel="cancelBackupCodes"
:disabled="backupCodes.inProgress">
<p class="warning">{{$t('settings.mfa.warning_of_generate_new_codes')}}</p>
</confirm>
</div>
</div>
</div> </div>
<div v-if="setupInProgress"> <!-- setup block--> <div>
<div
v-if="!setupInProgress"
class="setting-item"
>
<!-- Enabled methods -->
<h3>{{ $t('settings.mfa.authentication_methods') }}</h3>
<totp-item
:settings="settings"
@deactivate="fetchSettings"
@activate="activateOTP"
/>
<br>
<h3>{{$t('settings.mfa.setup_otp')}}</h3> <div v-if="settings.enabled">
<!-- backup codes block-->
<recovery-codes
v-if="!confirmNewBackupCodes"
:backup-codes="backupCodes"
/>
<button
v-if="!confirmNewBackupCodes"
class="btn btn-default"
@click="getBackupCodes"
>
{{ $t('settings.mfa.generate_new_recovery_codes') }}
</button>
<recovery-codes :backup-codes="backupCodes" v-if="!setupOTPInProgress"/> <div v-if="confirmNewBackupCodes">
<confirm
:disabled="backupCodes.inProgress"
<button class="btn btn-default" @click="cancelSetup" v-if="canSetupOTP"> @confirm="confirmBackupCodes"
{{$t('general.cancel')}} @cancel="cancelBackupCodes"
</button> >
<p class="warning">
<button class="btn btn-default" v-if="canSetupOTP" @click="setupOTP"> {{ $t('settings.mfa.warning_of_generate_new_codes') }}
{{$t('settings.mfa.setup_otp')}}
</button>
<template v-if="setupOTPInProgress">
<i v-if="prepareOTP">{{$t('settings.mfa.wait_pre_setup_otp')}}</i>
<div v-if="confirmOTP">
<div class="setup-otp">
<div class="qr-code">
<h4>{{$t('settings.mfa.scan.title')}}</h4>
<p>{{$t('settings.mfa.scan.desc')}}</p>
<qrcode :value="otpSettings.provisioning_uri" :options="{ width: 200 }"></qrcode>
<p>
{{$t('settings.mfa.scan.secret_code')}}:
{{otpSettings.key}}
</p> </p>
</div> </confirm>
<div class="verify">
<h4>{{$t('general.verify')}}</h4>
<p>{{$t('settings.mfa.verify.desc')}}</p>
<input type="text" v-model="otpConfirmToken">
<p>{{$t('settings.enter_current_password_to_confirm')}}:</p>
<input type="password" v-model="currentPassword">
<div class="confirm-otp-actions">
<button class="btn btn-default" @click="doConfirmOTP">
{{$t('settings.mfa.confirm_and_enable')}}
</button>
<button class="btn btn-default" @click="cancelSetup">
{{$t('general.cancel')}}
</button>
</div>
<div class="alert error" v-if="error">{{error}}</div>
</div>
</div> </div>
</div> </div>
</template> </div>
</div>
<div v-if="setupInProgress">
<!-- setup block-->
<h3>{{ $t('settings.mfa.setup_otp') }}</h3>
<recovery-codes
v-if="!setupOTPInProgress"
:backup-codes="backupCodes"
/>
<button
v-if="canSetupOTP"
class="btn btn-default"
@click="cancelSetup"
>
{{ $t('general.cancel') }}
</button>
<button
v-if="canSetupOTP"
class="btn btn-default"
@click="setupOTP"
>
{{ $t('settings.mfa.setup_otp') }}
</button>
<template v-if="setupOTPInProgress">
<i v-if="prepareOTP">{{ $t('settings.mfa.wait_pre_setup_otp') }}</i>
<div v-if="confirmOTP">
<div class="setup-otp">
<div class="qr-code">
<h4>{{ $t('settings.mfa.scan.title') }}</h4>
<p>{{ $t('settings.mfa.scan.desc') }}</p>
<qrcode
:value="otpSettings.provisioning_uri"
:options="{ width: 200 }"
/>
<p>
{{ $t('settings.mfa.scan.secret_code') }}:
{{ otpSettings.key }}
</p>
</div>
<div class="verify">
<h4>{{ $t('general.verify') }}</h4>
<p>{{ $t('settings.mfa.verify.desc') }}</p>
<input
v-model="otpConfirmToken"
type="text"
>
<p>{{ $t('settings.enter_current_password_to_confirm') }}:</p>
<input
v-model="currentPassword"
type="password"
>
<div class="confirm-otp-actions">
<button
class="btn btn-default"
@click="doConfirmOTP"
>
{{ $t('settings.mfa.confirm_and_enable') }}
</button>
<button
class="btn btn-default"
@click="cancelSetup"
>
{{ $t('general.cancel') }}
</button>
</div>
<div
v-if="error"
class="alert error"
>
{{ error }}
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div> </div>
</div>
</template> </template>
<script src="./mfa.js"></script> <script src="./mfa.js"></script>

View file

@ -1,12 +1,20 @@
<template> <template>
<div> <div>
<h4 v-if="displayTitle">{{$t('settings.mfa.recovery_codes')}}</h4> <h4 v-if="displayTitle">
<i v-if="inProgress">{{$t('settings.mfa.waiting_a_recovery_codes')}}</i> {{ $t('settings.mfa.recovery_codes') }}
<template v-if="ready"> </h4>
<p class="alert warning">{{$t('settings.mfa.recovery_codes_warning')}}</p> <i v-if="inProgress">{{ $t('settings.mfa.waiting_a_recovery_codes') }}</i>
<ul class="backup-codes"><li v-for="code in backupCodes.codes">{{code}}</li></ul> <template v-if="ready">
</template> <p class="alert warning">
</div> {{ $t('settings.mfa.recovery_codes_warning') }}
</p>
<ul class="backup-codes">
<li v-for="code in backupCodes.codes">
{{ code }}
</li>
</ul>
</template>
</div>
</template> </template>
<script src="./mfa_backup_codes.js"></script> <script src="./mfa_backup_codes.js"></script>
<style lang="scss"> <style lang="scss">

View file

@ -1,23 +1,43 @@
<template> <template>
<div> <div>
<div class="method-item"> <div class="method-item">
<strong>{{$t('settings.mfa.otp')}}</strong> <strong>{{ $t('settings.mfa.otp') }}</strong>
<button class="btn btn-default" v-if="!isActivated" @click="doActivate"> <button
{{$t('general.enable')}} v-if="!isActivated"
</button> class="btn btn-default"
@click="doActivate"
>
{{ $t('general.enable') }}
</button>
<button class="btn btn-default" :disabled="deactivate" @click="doDeactivate" <button
v-if="isActivated"> v-if="isActivated"
{{$t('general.disable')}} class="btn btn-default"
</button> :disabled="deactivate"
@click="doDeactivate"
>
{{ $t('general.disable') }}
</button>
</div>
<confirm
v-if="deactivate"
:disabled="inProgress"
@confirm="confirmDeactivate"
@cancel="cancelDeactivate"
>
{{ $t('settings.enter_current_password_to_confirm') }}:
<input
v-model="currentPassword"
type="password"
>
</confirm>
<div
v-if="error"
class="alert error"
>
{{ error }}
</div>
</div> </div>
<confirm @confirm="confirmDeactivate" @cancel="cancelDeactivate"
:disabled="inProgress" v-if="deactivate">
{{$t('settings.enter_current_password_to_confirm')}}:
<input type="password" v-model="currentPassword">
</confirm>
<div class="alert error" v-if="error">{{error}}</div>
</div>
</template> </template>
<script src="./mfa_totp.js"></script> <script src="./mfa_totp.js"></script>

View file

@ -2,15 +2,23 @@
<div class="settings panel panel-default"> <div class="settings panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<div class="title"> <div class="title">
{{$t('settings.user_settings')}} {{ $t('settings.user_settings') }}
</div> </div>
<transition name="fade"> <transition name="fade">
<template v-if="currentSaveStateNotice"> <template v-if="currentSaveStateNotice">
<div @click.prevent class="alert error" v-if="currentSaveStateNotice.error"> <div
v-if="currentSaveStateNotice.error"
class="alert error"
@click.prevent
>
{{ $t('settings.saving_err') }} {{ $t('settings.saving_err') }}
</div> </div>
<div @click.prevent class="alert transparent" v-if="!currentSaveStateNotice.error"> <div
v-if="!currentSaveStateNotice.error"
class="alert transparent"
@click.prevent
>
{{ $t('settings.saving_ok') }} {{ $t('settings.saving_ok') }}
</div> </div>
</template> </template>
@ -19,135 +27,267 @@
<div class="panel-body profile-edit"> <div class="panel-body profile-edit">
<tab-switcher> <tab-switcher>
<div :label="$t('settings.profile_tab')"> <div :label="$t('settings.profile_tab')">
<div class="setting-item" > <div class="setting-item">
<h2>{{$t('settings.name_bio')}}</h2> <h2>{{ $t('settings.name_bio') }}</h2>
<p>{{$t('settings.name')}}</p> <p>{{ $t('settings.name') }}</p>
<EmojiInput :suggest="emojiSuggestor" v-model="newName"> <EmojiInput
v-model="newName"
:suggest="emojiSuggestor"
>
<input <input
v-model="newName"
id="username" id="username"
v-model="newName"
classname="name-changer" classname="name-changer"
/> >
</EmojiInput> </EmojiInput>
<p>{{$t('settings.bio')}}</p> <p>{{ $t('settings.bio') }}</p>
<EmojiInput :suggest="emojiUserSuggestor" v-model="newBio"> <EmojiInput
v-model="newBio"
:suggest="emojiUserSuggestor"
>
<textarea <textarea
v-model="newBio" v-model="newBio"
classname="bio" classname="bio"
/> />
</EmojiInput> </EmojiInput>
<p> <p>
<input type="checkbox" v-model="newLocked" id="account-locked"> <input
<label for="account-locked">{{$t('settings.lock_account_description')}}</label> id="account-locked"
v-model="newLocked"
type="checkbox"
>
<label for="account-locked">{{ $t('settings.lock_account_description') }}</label>
</p> </p>
<div> <div>
<label for="default-vis">{{$t('settings.default_vis')}}</label> <label for="default-vis">{{ $t('settings.default_vis') }}</label>
<div id="default-vis" class="visibility-tray"> <div
id="default-vis"
class="visibility-tray"
>
<scope-selector <scope-selector
:showAll="true" :show-all="true"
:userDefault="newDefaultScope" :user-default="newDefaultScope"
:initialScope="newDefaultScope" :initial-scope="newDefaultScope"
:onScopeChange="changeVis"/> :on-scope-change="changeVis"
/>
</div> </div>
</div> </div>
<p> <p>
<input type="checkbox" v-model="newNoRichText" id="account-no-rich-text"> <input
<label for="account-no-rich-text">{{$t('settings.no_rich_text_description')}}</label> id="account-no-rich-text"
v-model="newNoRichText"
type="checkbox"
>
<label for="account-no-rich-text">{{ $t('settings.no_rich_text_description') }}</label>
</p> </p>
<p> <p>
<input type="checkbox" v-model="hideFollows" id="account-hide-follows"> <input
<label for="account-hide-follows">{{$t('settings.hide_follows_description')}}</label> id="account-hide-follows"
v-model="hideFollows"
type="checkbox"
>
<label for="account-hide-follows">{{ $t('settings.hide_follows_description') }}</label>
</p> </p>
<p> <p>
<input type="checkbox" v-model="hideFollowers" id="account-hide-followers"> <input
<label for="account-hide-followers">{{$t('settings.hide_followers_description')}}</label> id="account-hide-followers"
v-model="hideFollowers"
type="checkbox"
>
<label for="account-hide-followers">{{ $t('settings.hide_followers_description') }}</label>
</p> </p>
<p> <p>
<input type="checkbox" v-model="showRole" id="account-show-role"> <input
<label for="account-show-role" v-if="role === 'admin'">{{$t('settings.show_admin_badge')}}</label> id="account-show-role"
<label for="account-show-role" v-if="role === 'moderator'">{{$t('settings.show_moderator_badge')}}</label> v-model="showRole"
type="checkbox"
>
<label
v-if="role === 'admin'"
for="account-show-role"
>{{ $t('settings.show_admin_badge') }}</label>
<label
v-if="role === 'moderator'"
for="account-show-role"
>{{ $t('settings.show_moderator_badge') }}</label>
</p> </p>
<button :disabled='newName && newName.length === 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button> <button
:disabled="newName && newName.length === 0"
class="btn btn-default"
@click="updateProfile"
>
{{ $t('general.submit') }}
</button>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.avatar')}}</h2> <h2>{{ $t('settings.avatar') }}</h2>
<p class="visibility-notice">{{$t('settings.avatar_size_instruction')}}</p> <p class="visibility-notice">
<p>{{$t('settings.current_avatar')}}</p> {{ $t('settings.avatar_size_instruction') }}
<img :src="user.profile_image_url_original" class="current-avatar" /> </p>
<p>{{$t('settings.set_new_avatar')}}</p> <p>{{ $t('settings.current_avatar') }}</p>
<button class="btn" type="button" id="pick-avatar" v-show="pickAvatarBtnVisible">{{$t('settings.upload_a_photo')}}</button> <img
<image-cropper trigger="#pick-avatar" :submitHandler="submitAvatar" @open="pickAvatarBtnVisible=false" @close="pickAvatarBtnVisible=true" /> :src="user.profile_image_url_original"
class="current-avatar"
>
<p>{{ $t('settings.set_new_avatar') }}</p>
<button
v-show="pickAvatarBtnVisible"
id="pick-avatar"
class="btn"
type="button"
>
{{ $t('settings.upload_a_photo') }}
</button>
<image-cropper
trigger="#pick-avatar"
:submit-handler="submitAvatar"
@open="pickAvatarBtnVisible=false"
@close="pickAvatarBtnVisible=true"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.profile_banner')}}</h2> <h2>{{ $t('settings.profile_banner') }}</h2>
<p>{{$t('settings.current_profile_banner')}}</p> <p>{{ $t('settings.current_profile_banner') }}</p>
<img :src="user.cover_photo" class="banner" /> <img
<p>{{$t('settings.set_new_profile_banner')}}</p> :src="user.cover_photo"
<img class="banner" v-bind:src="bannerPreview" v-if="bannerPreview" /> class="banner"
>
<p>{{ $t('settings.set_new_profile_banner') }}</p>
<img
v-if="bannerPreview"
class="banner"
:src="bannerPreview"
>
<div> <div>
<input type="file" @change="uploadFile('banner', $event)" /> <input
type="file"
@change="uploadFile('banner', $event)"
>
</div> </div>
<i class=" icon-spin4 animate-spin uploading" v-if="bannerUploading"></i> <i
<button class="btn btn-default" v-else-if="bannerPreview" @click="submitBanner">{{$t('general.submit')}}</button> v-if="bannerUploading"
<div class='alert error' v-if="bannerUploadError"> class=" icon-spin4 animate-spin uploading"
/>
<button
v-else-if="bannerPreview"
class="btn btn-default"
@click="submitBanner"
>
{{ $t('general.submit') }}
</button>
<div
v-if="bannerUploadError"
class="alert error"
>
Error: {{ bannerUploadError }} Error: {{ bannerUploadError }}
<i class="button-icon icon-cancel" @click="clearUploadError('banner')"></i> <i
class="button-icon icon-cancel"
@click="clearUploadError('banner')"
/>
</div> </div>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.profile_background')}}</h2> <h2>{{ $t('settings.profile_background') }}</h2>
<p>{{$t('settings.set_new_profile_background')}}</p> <p>{{ $t('settings.set_new_profile_background') }}</p>
<img class="bg" v-bind:src="backgroundPreview" v-if="backgroundPreview" /> <img
v-if="backgroundPreview"
class="bg"
:src="backgroundPreview"
>
<div> <div>
<input type="file" @change="uploadFile('background', $event)" /> <input
type="file"
@change="uploadFile('background', $event)"
>
</div> </div>
<i class=" icon-spin4 animate-spin uploading" v-if="backgroundUploading"></i> <i
<button class="btn btn-default" v-else-if="backgroundPreview" @click="submitBg">{{$t('general.submit')}}</button> v-if="backgroundUploading"
<div class='alert error' v-if="backgroundUploadError"> class=" icon-spin4 animate-spin uploading"
/>
<button
v-else-if="backgroundPreview"
class="btn btn-default"
@click="submitBg"
>
{{ $t('general.submit') }}
</button>
<div
v-if="backgroundUploadError"
class="alert error"
>
Error: {{ backgroundUploadError }} Error: {{ backgroundUploadError }}
<i class="button-icon icon-cancel" @click="clearUploadError('background')"></i> <i
class="button-icon icon-cancel"
@click="clearUploadError('background')"
/>
</div> </div>
</div> </div>
</div> </div>
<div :label="$t('settings.security_tab')"> <div :label="$t('settings.security_tab')">
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.change_password')}}</h2> <h2>{{ $t('settings.change_password') }}</h2>
<div> <div>
<p>{{$t('settings.current_password')}}</p> <p>{{ $t('settings.current_password') }}</p>
<input type="password" v-model="changePasswordInputs[0]"> <input
v-model="changePasswordInputs[0]"
type="password"
>
</div> </div>
<div> <div>
<p>{{$t('settings.new_password')}}</p> <p>{{ $t('settings.new_password') }}</p>
<input type="password" v-model="changePasswordInputs[1]"> <input
v-model="changePasswordInputs[1]"
type="password"
>
</div> </div>
<div> <div>
<p>{{$t('settings.confirm_new_password')}}</p> <p>{{ $t('settings.confirm_new_password') }}</p>
<input type="password" v-model="changePasswordInputs[2]"> <input
v-model="changePasswordInputs[2]"
type="password"
>
</div> </div>
<button class="btn btn-default" @click="changePassword">{{$t('general.submit')}}</button> <button
<p v-if="changedPassword">{{$t('settings.changed_password')}}</p> class="btn btn-default"
<p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p> @click="changePassword"
<p v-if="changePasswordError">{{changePasswordError}}</p> >
{{ $t('general.submit') }}
</button>
<p v-if="changedPassword">
{{ $t('settings.changed_password') }}
</p>
<p v-else-if="changePasswordError !== false">
{{ $t('settings.change_password_error') }}
</p>
<p v-if="changePasswordError">
{{ changePasswordError }}
</p>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.oauth_tokens')}}</h2> <h2>{{ $t('settings.oauth_tokens') }}</h2>
<table class="oauth-tokens"> <table class="oauth-tokens">
<thead> <thead>
<tr> <tr>
<th>{{$t('settings.app_name')}}</th> <th>{{ $t('settings.app_name') }}</th>
<th>{{$t('settings.valid_until')}}</th> <th>{{ $t('settings.valid_until') }}</th>
<th></th> <th />
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="oauthToken in oauthTokens" :key="oauthToken.id"> <tr
<td>{{oauthToken.appName}}</td> v-for="oauthToken in oauthTokens"
<td>{{oauthToken.validUntil}}</td> :key="oauthToken.id"
>
<td>{{ oauthToken.appName }}</td>
<td>{{ oauthToken.validUntil }}</td>
<td class="actions"> <td class="actions">
<button class="btn btn-default" @click="revokeToken(oauthToken.id)"> <button
{{$t('settings.revoke_token')}} class="btn btn-default"
@click="revokeToken(oauthToken.id)"
>
{{ $t('settings.revoke_token') }}
</button> </button>
</td> </td>
</tr> </tr>
@ -156,123 +296,250 @@
</div> </div>
<mfa /> <mfa />
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.delete_account')}}</h2> <h2>{{ $t('settings.delete_account') }}</h2>
<p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p> <p v-if="!deletingAccount">
{{ $t('settings.delete_account_description') }}
</p>
<div v-if="deletingAccount"> <div v-if="deletingAccount">
<p>{{$t('settings.delete_account_instructions')}}</p> <p>{{ $t('settings.delete_account_instructions') }}</p>
<p>{{$t('login.password')}}</p> <p>{{ $t('login.password') }}</p>
<input type="password" v-model="deleteAccountConfirmPasswordInput"> <input
<button class="btn btn-default" @click="deleteAccount">{{$t('settings.delete_account')}}</button> v-model="deleteAccountConfirmPasswordInput"
type="password"
>
<button
class="btn btn-default"
@click="deleteAccount"
>
{{ $t('settings.delete_account') }}
</button>
</div> </div>
<p v-if="deleteAccountError !== false">{{$t('settings.delete_account_error')}}</p> <p v-if="deleteAccountError !== false">
<p v-if="deleteAccountError">{{deleteAccountError}}</p> {{ $t('settings.delete_account_error') }}
<button class="btn btn-default" v-if="!deletingAccount" @click="confirmDelete">{{$t('general.submit')}}</button> </p>
<p v-if="deleteAccountError">
{{ deleteAccountError }}
</p>
<button
v-if="!deletingAccount"
class="btn btn-default"
@click="confirmDelete"
>
{{ $t('general.submit') }}
</button>
</div> </div>
</div> </div>
<div :label="$t('settings.notifications')" v-if="pleromaBackend"> <div
v-if="pleromaBackend"
:label="$t('settings.notifications')"
>
<div class="setting-item"> <div class="setting-item">
<div class="select-multiple"> <div class="select-multiple">
<span class="label">{{$t('settings.notification_setting')}}</span> <span class="label">{{ $t('settings.notification_setting') }}</span>
<ul class="option-list"> <ul class="option-list">
<li> <li>
<input type="checkbox" id="notification-setting-follows" v-model="notificationSettings.follows"> <input
id="notification-setting-follows"
v-model="notificationSettings.follows"
type="checkbox"
>
<label for="notification-setting-follows"> <label for="notification-setting-follows">
{{$t('settings.notification_setting_follows')}} {{ $t('settings.notification_setting_follows') }}
</label> </label>
</li> </li>
<li> <li>
<input type="checkbox" id="notification-setting-followers" v-model="notificationSettings.followers"> <input
id="notification-setting-followers"
v-model="notificationSettings.followers"
type="checkbox"
>
<label for="notification-setting-followers"> <label for="notification-setting-followers">
{{$t('settings.notification_setting_followers')}} {{ $t('settings.notification_setting_followers') }}
</label> </label>
</li> </li>
<li> <li>
<input type="checkbox" id="notification-setting-non-follows" v-model="notificationSettings.non_follows"> <input
id="notification-setting-non-follows"
v-model="notificationSettings.non_follows"
type="checkbox"
>
<label for="notification-setting-non-follows"> <label for="notification-setting-non-follows">
{{$t('settings.notification_setting_non_follows')}} {{ $t('settings.notification_setting_non_follows') }}
</label> </label>
</li> </li>
<li> <li>
<input type="checkbox" id="notification-setting-non-followers" v-model="notificationSettings.non_followers"> <input
id="notification-setting-non-followers"
v-model="notificationSettings.non_followers"
type="checkbox"
>
<label for="notification-setting-non-followers"> <label for="notification-setting-non-followers">
{{$t('settings.notification_setting_non_followers')}} {{ $t('settings.notification_setting_non_followers') }}
</label> </label>
</li> </li>
</ul> </ul>
</div> </div>
<p>{{$t('settings.notification_mutes')}}</p> <p>{{ $t('settings.notification_mutes') }}</p>
<p>{{$t('settings.notification_blocks')}}</p> <p>{{ $t('settings.notification_blocks') }}</p>
<button class="btn btn-default" @click="updateNotificationSettings">{{$t('general.submit')}}</button> <button
class="btn btn-default"
@click="updateNotificationSettings"
>
{{ $t('general.submit') }}
</button>
</div> </div>
</div> </div>
<div :label="$t('settings.data_import_export_tab')" v-if="pleromaBackend"> <div
v-if="pleromaBackend"
:label="$t('settings.data_import_export_tab')"
>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.follow_import')}}</h2> <h2>{{ $t('settings.follow_import') }}</h2>
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p> <p>{{ $t('settings.import_followers_from_a_csv_file') }}</p>
<Importer :submitHandler="importFollows" :successMessage="$t('settings.follows_imported')" :errorMessage="$t('settings.follow_import_error')" /> <Importer
:submit-handler="importFollows"
:success-message="$t('settings.follows_imported')"
:error-message="$t('settings.follow_import_error')"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.follow_export')}}</h2> <h2>{{ $t('settings.follow_export') }}</h2>
<Exporter :getContent="getFollowsContent" filename="friends.csv" :exportButtonLabel="$t('settings.follow_export_button')" /> <Exporter
:get-content="getFollowsContent"
filename="friends.csv"
:export-button-label="$t('settings.follow_export_button')"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.block_import')}}</h2> <h2>{{ $t('settings.block_import') }}</h2>
<p>{{$t('settings.import_blocks_from_a_csv_file')}}</p> <p>{{ $t('settings.import_blocks_from_a_csv_file') }}</p>
<Importer :submitHandler="importBlocks" :successMessage="$t('settings.blocks_imported')" :errorMessage="$t('settings.block_import_error')" /> <Importer
:submit-handler="importBlocks"
:success-message="$t('settings.blocks_imported')"
:error-message="$t('settings.block_import_error')"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{$t('settings.block_export')}}</h2> <h2>{{ $t('settings.block_export') }}</h2>
<Exporter :getContent="getBlocksContent" filename="blocks.csv" :exportButtonLabel="$t('settings.block_export_button')" /> <Exporter
:get-content="getBlocksContent"
filename="blocks.csv"
:export-button-label="$t('settings.block_export_button')"
/>
</div> </div>
</div> </div>
<div :label="$t('settings.blocks_tab')"> <div :label="$t('settings.blocks_tab')">
<div class="profile-edit-usersearch-wrapper"> <div class="profile-edit-usersearch-wrapper">
<Autosuggest :filter="filterUnblockedUsers" :query="queryUserIds" :placeholder="$t('settings.search_user_to_block')"> <Autosuggest
<BlockCard slot-scope="row" :userId="row.item"/> :filter="filterUnblockedUsers"
:query="queryUserIds"
:placeholder="$t('settings.search_user_to_block')"
>
<BlockCard
slot-scope="row"
:user-id="row.item"
/>
</Autosuggest> </Autosuggest>
</div> </div>
<BlockList :refresh="true" :getKey="identity"> <BlockList
<template slot="header" slot-scope="{selected}"> :refresh="true"
:get-key="identity"
>
<template
slot="header"
slot-scope="{selected}"
>
<div class="profile-edit-bulk-actions"> <div class="profile-edit-bulk-actions">
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => blockUsers(selected)"> <ProgressButton
v-if="selected.length > 0"
class="btn btn-default"
:click="() => blockUsers(selected)"
>
{{ $t('user_card.block') }} {{ $t('user_card.block') }}
<template slot="progress">{{ $t('user_card.block_progress') }}</template> <template slot="progress">
{{ $t('user_card.block_progress') }}
</template>
</ProgressButton> </ProgressButton>
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unblockUsers(selected)"> <ProgressButton
v-if="selected.length > 0"
class="btn btn-default"
:click="() => unblockUsers(selected)"
>
{{ $t('user_card.unblock') }} {{ $t('user_card.unblock') }}
<template slot="progress">{{ $t('user_card.unblock_progress') }}</template> <template slot="progress">
{{ $t('user_card.unblock_progress') }}
</template>
</ProgressButton> </ProgressButton>
</div> </div>
</template> </template>
<template slot="item" slot-scope="{item}"><BlockCard :userId="item" /></template> <template
<template slot="empty">{{$t('settings.no_blocks')}}</template> slot="item"
slot-scope="{item}"
>
<BlockCard :user-id="item" />
</template>
<template slot="empty">
{{ $t('settings.no_blocks') }}
</template>
</BlockList> </BlockList>
</div> </div>
<div :label="$t('settings.mutes_tab')"> <div :label="$t('settings.mutes_tab')">
<div class="profile-edit-usersearch-wrapper"> <div class="profile-edit-usersearch-wrapper">
<Autosuggest :filter="filterUnMutedUsers" :query="queryUserIds" :placeholder="$t('settings.search_user_to_mute')"> <Autosuggest
<MuteCard slot-scope="row" :userId="row.item"/> :filter="filterUnMutedUsers"
:query="queryUserIds"
:placeholder="$t('settings.search_user_to_mute')"
>
<MuteCard
slot-scope="row"
:user-id="row.item"
/>
</Autosuggest> </Autosuggest>
</div> </div>
<MuteList :refresh="true" :getKey="identity"> <MuteList
<template slot="header" slot-scope="{selected}"> :refresh="true"
:get-key="identity"
>
<template
slot="header"
slot-scope="{selected}"
>
<div class="profile-edit-bulk-actions"> <div class="profile-edit-bulk-actions">
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => muteUsers(selected)"> <ProgressButton
v-if="selected.length > 0"
class="btn btn-default"
:click="() => muteUsers(selected)"
>
{{ $t('user_card.mute') }} {{ $t('user_card.mute') }}
<template slot="progress">{{ $t('user_card.mute_progress') }}</template> <template slot="progress">
{{ $t('user_card.mute_progress') }}
</template>
</ProgressButton> </ProgressButton>
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unmuteUsers(selected)"> <ProgressButton
v-if="selected.length > 0"
class="btn btn-default"
:click="() => unmuteUsers(selected)"
>
{{ $t('user_card.unmute') }} {{ $t('user_card.unmute') }}
<template slot="progress">{{ $t('user_card.unmute_progress') }}</template> <template slot="progress">
{{ $t('user_card.unmute_progress') }}
</template>
</ProgressButton> </ProgressButton>
</div> </div>
</template> </template>
<template slot="item" slot-scope="{item}"><MuteCard :userId="item" /></template> <template
<template slot="empty">{{$t('settings.no_mutes')}}</template> slot="item"
slot-scope="{item}"
>
<MuteCard :user-id="item" />
</template>
<template slot="empty">
{{ $t('settings.no_mutes') }}
</template>
</MuteList> </MuteList>
</div> </div>
</tab-switcher> </tab-switcher>

View file

@ -1,10 +1,11 @@
<template> <template>
<video class="video" <video
@loadeddata="onVideoDataLoad" class="video"
:src="attachment.url" :src="attachment.url"
:loop="loopVideo" :loop="loopVideo"
:controls="controls" :controls="controls"
playsinline playsinline
@loadeddata="onVideoDataLoad"
/> />
</template> </template>

View file

@ -1,10 +1,15 @@
<template> <template>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{$t('who_to_follow.who_to_follow')}} {{ $t('who_to_follow.who_to_follow') }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/> <FollowCard
v-for="user in users"
:key="user.id"
:user="user"
class="list-item"
/>
</div> </div>
</div> </div>
</template> </template>

View file

@ -3,19 +3,22 @@
<div class="panel panel-default base01-background"> <div class="panel panel-default base01-background">
<div class="panel-heading timeline-heading base02-background base04"> <div class="panel-heading timeline-heading base02-background base04">
<div class="title"> <div class="title">
{{$t('who_to_follow.who_to_follow')}} {{ $t('who_to_follow.who_to_follow') }}
</div> </div>
</div> </div>
<div class="who-to-follow"> <div class="who-to-follow">
<p v-for="user in usersToFollow" class="who-to-follow-items"> <p
<img v-bind:src="user.img" /> v-for="user in usersToFollow"
<router-link v-bind:to="userProfileLink(user.id, user.name)"> class="who-to-follow-items"
{{user.name}} >
</router-link><br /> <img :src="user.img">
<router-link :to="userProfileLink(user.id, user.name)">
{{ user.name }}
</router-link><br>
</p> </p>
<p class="who-to-follow-more"> <p class="who-to-follow-more">
<router-link :to="{ name: 'who-to-follow' }"> <router-link :to="{ name: 'who-to-follow' }">
{{$t('who_to_follow.more')}} {{ $t('who_to_follow.more') }}
</router-link> </router-link>
</p> </p>
</div> </div>