summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locales/ja-JP.yml14
-rw-r--r--src/client/app/common/views/components/activity.vue (renamed from src/client/app/mobile/views/components/activity.vue)25
-rw-r--r--src/client/app/common/views/components/dummy.vue11
-rw-r--r--src/client/app/common/views/components/follow-button.vue11
-rw-r--r--src/client/app/common/views/components/index.ts2
-rw-r--r--src/client/app/common/views/widgets/index.ts2
-rw-r--r--src/client/app/common/views/widgets/instance.vue14
-rw-r--r--src/client/app/desktop/script.ts37
-rw-r--r--src/client/app/desktop/views/components/home.vue396
-rw-r--r--src/client/app/desktop/views/components/index.ts4
-rw-r--r--src/client/app/desktop/views/components/settings.vue19
-rw-r--r--src/client/app/desktop/views/components/ui.header.account.vue7
-rw-r--r--src/client/app/desktop/views/components/ui.header.nav.vue19
-rw-r--r--src/client/app/desktop/views/components/ui.sidebar.vue2
-rw-r--r--src/client/app/desktop/views/deck/deck.column-core.vue (renamed from src/client/app/desktop/views/pages/deck/deck.column-core.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.column.vue)11
-rw-r--r--src/client/app/desktop/views/deck/deck.direct-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.direct-column.vue)2
-rw-r--r--src/client/app/desktop/views/deck/deck.direct.vue (renamed from src/client/app/desktop/views/pages/deck/deck.direct.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.favorites-column.vue88
-rw-r--r--src/client/app/desktop/views/deck/deck.hashtag-column.vue119
-rw-r--r--src/client/app/desktop/views/deck/deck.hashtag-tl.vue (renamed from src/client/app/desktop/views/pages/deck/deck.hashtag-tl.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.list-tl.vue (renamed from src/client/app/desktop/views/pages/deck/deck.list-tl.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.mentions-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.mentions-column.vue)2
-rw-r--r--src/client/app/desktop/views/deck/deck.mentions.vue (renamed from src/client/app/desktop/views/pages/deck/deck.mentions.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.note-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.note-column.vue)33
-rw-r--r--src/client/app/desktop/views/deck/deck.notes.vue (renamed from src/client/app/desktop/views/pages/deck/deck.notes.vue)6
-rw-r--r--src/client/app/desktop/views/deck/deck.notification.vue (renamed from src/client/app/desktop/views/pages/deck/deck.notification.vue)4
-rw-r--r--src/client/app/desktop/views/deck/deck.notifications-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.notifications-column.vue)2
-rw-r--r--src/client/app/desktop/views/deck/deck.notifications.vue (renamed from src/client/app/desktop/views/pages/deck/deck.notifications.vue)2
-rw-r--r--src/client/app/desktop/views/deck/deck.tl-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.tl-column.vue)2
-rw-r--r--src/client/app/desktop/views/deck/deck.tl.vue (renamed from src/client/app/desktop/views/pages/deck/deck.tl.vue)0
-rw-r--r--src/client/app/desktop/views/deck/deck.user-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.user-column.vue)224
-rw-r--r--src/client/app/desktop/views/deck/deck.vue (renamed from src/client/app/desktop/views/pages/deck/deck.vue)62
-rw-r--r--src/client/app/desktop/views/deck/deck.widgets-column.vue (renamed from src/client/app/desktop/views/pages/deck/deck.widgets-column.vue)2
-rw-r--r--src/client/app/desktop/views/home/favorites.vue (renamed from src/client/app/desktop/views/pages/favorites.vue)26
-rw-r--r--src/client/app/desktop/views/home/home.vue400
-rw-r--r--src/client/app/desktop/views/home/note.vue (renamed from src/client/app/desktop/views/pages/note.vue)19
-rw-r--r--src/client/app/desktop/views/home/tag.vue (renamed from src/client/app/desktop/views/pages/tag.vue)21
-rw-r--r--src/client/app/desktop/views/home/timeline.core.vue (renamed from src/client/app/desktop/views/components/timeline.core.vue)0
-rw-r--r--src/client/app/desktop/views/home/timeline.vue (renamed from src/client/app/desktop/views/components/timeline.vue)169
-rw-r--r--src/client/app/desktop/views/home/user/user.followers-you-know.vue (renamed from src/client/app/desktop/views/pages/user/user.followers-you-know.vue)0
-rw-r--r--src/client/app/desktop/views/home/user/user.friends.vue (renamed from src/client/app/desktop/views/pages/user/user.friends.vue)0
-rw-r--r--src/client/app/desktop/views/home/user/user.header.vue (renamed from src/client/app/desktop/views/pages/user/user.header.vue)19
-rw-r--r--src/client/app/desktop/views/home/user/user.integrations.integration.vue (renamed from src/client/app/desktop/views/pages/user/user.integrations.integration.vue)0
-rw-r--r--src/client/app/desktop/views/home/user/user.integrations.vue (renamed from src/client/app/desktop/views/pages/user/user.integrations.vue)0
-rw-r--r--src/client/app/desktop/views/home/user/user.photos.vue (renamed from src/client/app/desktop/views/pages/user/user.photos.vue)2
-rw-r--r--src/client/app/desktop/views/home/user/user.timeline.vue (renamed from src/client/app/desktop/views/pages/user/user.timeline.vue)0
-rw-r--r--src/client/app/desktop/views/home/user/user.vue109
-rw-r--r--src/client/app/desktop/views/pages/deck/deck.hashtag-column.vue112
-rw-r--r--src/client/app/desktop/views/pages/home-customize.vue3
-rw-r--r--src/client/app/desktop/views/pages/home.vue39
-rw-r--r--src/client/app/desktop/views/pages/index.vue25
-rw-r--r--src/client/app/desktop/views/pages/user/user.profile.vue66
-rw-r--r--src/client/app/desktop/views/pages/user/user.vue155
-rw-r--r--src/client/app/desktop/views/widgets/customize.vue21
-rw-r--r--src/client/app/desktop/views/widgets/index.ts2
-rw-r--r--src/client/app/init.ts9
-rw-r--r--src/client/app/mobile/views/pages/user/home.vue2
-rw-r--r--src/client/app/mobile/views/widgets/activity.vue2
-rw-r--r--src/client/app/store.ts9
60 files changed, 1121 insertions, 1211 deletions
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 27542dd96c..7df81de90a 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -28,6 +28,7 @@ common:
load-more: "もっと読み込む"
enter-password: "パスワードを入力してください"
2fa: "二段階認証"
+ customize-home: "ホームをカスタマイズ"
got-it: "わかった"
customization-tips:
@@ -893,14 +894,10 @@ desktop/views/components/settings.vue:
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
- deck-nav: "デッキ内ナビゲーション"
- deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
keep-cw: "CW保持"
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
- deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
- customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
@@ -1076,7 +1073,6 @@ desktop/views/components/ui.header.account.vue:
favorites: "お気に入り"
lists: "リスト"
follow-requests: "フォロー申請"
- customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
@@ -1447,9 +1443,6 @@ desktop/views/pages/welcome.vue:
desktop/views/pages/drive.vue:
title: "Misskey Drive"
-desktop/views/pages/home-customize.vue:
- title: "ホームのカスタマイズ"
-
desktop/views/pages/note.vue:
prev: "前の投稿"
next: "次の投稿"
@@ -1490,10 +1483,6 @@ desktop/views/pages/user/user.photos.vue:
loading: "読み込み中"
no-photos: "写真はありません"
-desktop/views/pages/user/user.profile.vue:
- follows-you: "フォローされています"
- menu: "メニュー"
-
desktop/views/pages/user/user.header.vue:
posts: "投稿"
following: "フォロー"
@@ -1503,6 +1492,7 @@ desktop/views/pages/user/user.header.vue:
year: "年"
month: "月"
day: "日"
+ follows-you: "フォローされています"
desktop/views/pages/user/user.timeline.vue:
default: "投稿"
diff --git a/src/client/app/mobile/views/components/activity.vue b/src/client/app/common/views/components/activity.vue
index f06dddfc46..1e9f87cf04 100644
--- a/src/client/app/mobile/views/components/activity.vue
+++ b/src/client/app/common/views/components/activity.vue
@@ -1,5 +1,5 @@
<template>
-<div class="mk-activity">
+<div>
<div ref="chart"></div>
</div>
</template>
@@ -9,7 +9,17 @@ import Vue from 'vue';
import ApexCharts from 'apexcharts';
export default Vue.extend({
- props: ['user'],
+ props: {
+ user: {
+ type: Object,
+ required: true
+ },
+ limit: {
+ type: Number,
+ required: false,
+ default: 21
+ }
+ },
data() {
return {
fetching: true,
@@ -21,7 +31,7 @@ export default Vue.extend({
this.$root.api('charts/user/notes', {
userId: this.user.id,
span: 'day',
- limit: 21
+ limit: this.limit
}).then(stats => {
const normal = [];
const reply = [];
@@ -32,7 +42,7 @@ export default Vue.extend({
const m = now.getMonth();
const d = now.getDate();
- for (let i = 0; i < 21; i++) {
+ for (let i = 0; i < this.limit; i++) {
const x = new Date(y, m, d - i);
normal.push([
x,
@@ -99,10 +109,3 @@ export default Vue.extend({
}
});
</script>
-
-<style lang="stylus" scoped>
-.mk-activity
- max-width 600px
- margin 0 auto
-
-</style>
diff --git a/src/client/app/common/views/components/dummy.vue b/src/client/app/common/views/components/dummy.vue
new file mode 100644
index 0000000000..5634efc509
--- /dev/null
+++ b/src/client/app/common/views/components/dummy.vue
@@ -0,0 +1,11 @@
+<template>
+<div>
+ <slot></slot>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+});
+</script>
diff --git a/src/client/app/common/views/components/follow-button.vue b/src/client/app/common/views/components/follow-button.vue
index 6d120f52b4..71d3a63e4c 100644
--- a/src/client/app/common/views/components/follow-button.vue
+++ b/src/client/app/common/views/components/follow-button.vue
@@ -1,8 +1,9 @@
<template>
<button class="wfliddvnhxvyusikowhxozkyxyenqxqr"
- :class="{ wait, block, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
+ :class="{ wait, block, inline, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
@click="onClick"
:disabled="wait"
+ :inline="inline"
>
<template v-if="!wait">
<fa :icon="iconAndText[0]"/> <template v-if="!mini">{{ iconAndText[1] }}</template>
@@ -28,6 +29,11 @@ export default Vue.extend({
required: false,
default: false
},
+ inline: {
+ type: Boolean,
+ required: false,
+ default: false
+ },
mini: {
type: Boolean,
required: false,
@@ -128,6 +134,9 @@ export default Vue.extend({
border solid 1px var(--primary)
border-radius 36px
+ &.inline
+ display inline-block
+
&.mini
padding 0
min-width 0
diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts
index e6f93bb840..f60f7391d2 100644
--- a/src/client/app/common/views/components/index.ts
+++ b/src/client/app/common/views/components/index.ts
@@ -1,5 +1,6 @@
import Vue from 'vue';
+import dummy from './dummy.vue';
import userName from './user-name.vue';
import followButton from './follow-button.vue';
import error from './error.vue';
@@ -46,6 +47,7 @@ import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue';
Vue.component('mfm', misskeyFlavoredMarkdown);
+Vue.component('mk-dummy', dummy);
Vue.component('mk-user-name', userName);
Vue.component('mk-follow-button', followButton);
Vue.component('mk-error', error);
diff --git a/src/client/app/common/views/widgets/index.ts b/src/client/app/common/views/widgets/index.ts
index 7fca79f1fc..6b198ccd51 100644
--- a/src/client/app/common/views/widgets/index.ts
+++ b/src/client/app/common/views/widgets/index.ts
@@ -13,6 +13,7 @@ import wSlideshow from './slideshow.vue';
import wTips from './tips.vue';
import wNav from './nav.vue';
import wHashtags from './hashtags.vue';
+import wInstance from './instance.vue';
Vue.component('mkw-analog-clock', wAnalogClock);
Vue.component('mkw-nav', wNav);
@@ -27,3 +28,4 @@ Vue.component('mkw-memo', wMemo);
Vue.component('mkw-rss', wRss);
Vue.component('mkw-version', wVersion);
Vue.component('mkw-hashtags', wHashtags);
+Vue.component('mkw-instance', wInstance);
diff --git a/src/client/app/common/views/widgets/instance.vue b/src/client/app/common/views/widgets/instance.vue
new file mode 100644
index 0000000000..1053235618
--- /dev/null
+++ b/src/client/app/common/views/widgets/instance.vue
@@ -0,0 +1,14 @@
+<template>
+<div class="mkw-instance">
+ <mk-widget-container>
+ <mk-instance/>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../common/define-widget';
+export default define({
+ name: 'instance'
+});
+</script>
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 05cd79f706..26fe273394 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -12,19 +12,13 @@ import init from '../init';
import fuckAdBlock from '../common/scripts/fuck-ad-block';
import composeNotification from '../common/scripts/compose-notification';
-import MkIndex from './views/pages/index.vue';
-import MkHome from './views/pages/home.vue';
-import MkDeck from './views/pages/deck/deck.vue';
-import MkUser from './views/pages/user/user.vue';
+import MkHome from './views/home/home.vue';
+import MkDeck from './views/deck/deck.vue';
import MkUserFollowingOrFollowers from './views/pages/user-following-or-followers.vue';
-import MkFavorites from './views/pages/favorites.vue';
import MkSelectDrive from './views/pages/selectdrive.vue';
import MkDrive from './views/pages/drive.vue';
-import MkHomeCustomize from './views/pages/home-customize.vue';
import MkMessagingRoom from './views/pages/messaging-room.vue';
-import MkNote from './views/pages/note.vue';
import MkSearch from './views/pages/search.vue';
-import MkTag from './views/pages/tag.vue';
import MkReversi from './views/pages/games/reversi.vue';
import MkShare from './views/pages/share.vue';
import MkFollow from '../common/views/pages/follow.vue';
@@ -36,6 +30,7 @@ import PostFormWindow from './views/components/post-form-window.vue';
import RenoteFormWindow from './views/components/renote-form-window.vue';
import MkChooseFileFromDriveWindow from './views/components/choose-file-from-drive-window.vue';
import MkChooseFolderFromDriveWindow from './views/components/choose-folder-from-drive-window.vue';
+import MkHomeTimeline from './views/home/timeline.vue';
import Notification from './views/components/ui-notification.vue';
import { url } from '../config';
@@ -44,7 +39,7 @@ import MiOS from '../mios';
/**
* init
*/
-init(async (launch) => {
+init(async (launch, os) => {
Vue.mixin({
methods: {
$contextmenu(e, menu, opts?) {
@@ -134,31 +129,37 @@ init(async (launch) => {
const router = new VueRouter({
mode: 'history',
routes: [
- { path: '/', name: 'index', component: MkIndex },
- { path: '/home', name: 'home', component: MkHome },
- { path: '/deck', name: 'deck', component: MkDeck },
- { path: '/i/customize-home', component: MkHomeCustomize },
- { path: '/i/favorites', component: MkFavorites },
+ os.store.getters.isSignedIn && os.store.state.device.deckMode
+ ? { path: '/', name: 'index', component: MkDeck, children: [
+ { path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default) },
+ { path: '/notes/:note', name: 'note', component: () => import('./views/deck/deck.note-column.vue').then(m => m.default) },
+ { path: '/tags/:tag', name: 'tag', component: () => import('./views/deck/deck.hashtag-column.vue').then(m => m.default) },
+ { path: '/i/favorites', component: () => import('./views/deck/deck.favorites-column.vue').then(m => m.default) }
+ ]}
+ : { path: '/', component: MkHome, children: [
+ { path: '', name: 'index', component: MkHomeTimeline },
+ { path: '/@:user', name: 'user', component: () => import('./views/home/user/user.vue').then(m => m.default) },
+ { path: '/notes/:note', name: 'note', component: () => import('./views/home/note.vue').then(m => m.default) },
+ { path: '/tags/:tag', name: 'tag', component: () => import('./views/home/tag.vue').then(m => m.default) },
+ { path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) }
+ ]},
{ path: '/i/messaging/:user', component: MkMessagingRoom },
{ path: '/i/drive', component: MkDrive },
{ path: '/i/drive/folder/:folder', component: MkDrive },
{ path: '/i/settings', component: MkSettings },
{ path: '/selectdrive', component: MkSelectDrive },
{ path: '/search', component: MkSearch },
- { path: '/tags/:tag', name: 'tag', component: MkTag },
{ path: '/share', component: MkShare },
{ path: '/games/reversi/:game?', component: MkReversi },
- { path: '/@:user', name: 'user', component: MkUser },
{ path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers },
{ path: '/@:user/followers', name: 'userFollowers', component: MkUserFollowingOrFollowers },
- { path: '/notes/:note', name: 'note', component: MkNote },
{ path: '/authorize-follow', component: MkFollow },
{ path: '*', component: MkNotFound }
]
});
// Launch the app
- const [app, os] = launch(router);
+ const [app, _] = launch(router);
if (os.store.getters.isSignedIn) {
/**
diff --git a/src/client/app/desktop/views/components/home.vue b/src/client/app/desktop/views/components/home.vue
deleted file mode 100644
index 18cb215202..0000000000
--- a/src/client/app/desktop/views/components/home.vue
+++ /dev/null
@@ -1,396 +0,0 @@
-<template>
-<div class="mk-home" :data-customize="customize">
- <div class="customize" v-if="customize">
- <router-link to="/"><fa icon="check"/>{{ $t('done') }}</router-link>
- <div>
- <div class="adder">
- <p>{{ $t('add-widget') }}</p>
- <select v-model="widgetAdderSelected">
- <option value="profile">{{ $t('@.widgets.profile') }}</option>
- <option value="analog-clock">{{ $t('@.widgets.analog-clock') }}</option>
- <option value="calendar">{{ $t('@.widgets.calendar') }}</option>
- <option value="timemachine">{{ $t('@.widgets.timemachine') }}</option>
- <option value="activity">{{ $t('@.widgets.activity') }}</option>
- <option value="rss">{{ $t('@.widgets.rss') }}</option>
- <option value="trends">{{ $t('@.widgets.trends') }}</option>
- <option value="photo-stream">{{ $t('@.widgets.photo-stream') }}</option>
- <option value="slideshow">{{ $t('@.widgets.slideshow') }}</option>
- <option value="version">{{ $t('@.widgets.version') }}</option>
- <option value="broadcast">{{ $t('@.widgets.broadcast') }}</option>
- <option value="notifications">{{ $t('@.widgets.notifications') }}</option>
- <option value="users">{{ $t('@.widgets.users') }}</option>
- <option value="polls">{{ $t('@.widgets.polls') }}</option>
- <option value="post-form">{{ $t('@.widgets.post-form') }}</option>
- <option value="messaging">{{ $t('@.widgets.messaging') }}</option>
- <option value="memo">{{ $t('@.widgets.memo') }}</option>
- <option value="hashtags">{{ $t('@.widgets.hashtags') }}</option>
- <option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option>
- <option value="server">{{ $t('@.widgets.server') }}</option>
- <option value="nav">{{ $t('@.widgets.nav') }}</option>
- <option value="tips">{{ $t('@.widgets.tips') }}</option>
- </select>
- <button @click="addWidget">{{ $t('add') }}</button>
- </div>
- <div class="trash">
- <x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable>
- <p>{{ $t('@.trash') }}</p>
- </div>
- </div>
- </div>
- <div class="main" :class="{ side: widgets.left.length == 0 || widgets.right.length == 0 }">
- <template v-if="customize">
- <x-draggable v-for="place in ['left', 'right']"
- :list="widgets[place]"
- :class="place"
- :data-place="place"
- :options="{ group: 'x', animation: 150 }"
- @sort="onWidgetSort"
- :key="place"
- >
- <div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
- <component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
- </div>
- </x-draggable>
- <div class="main">
- <a @click="hint">{{ $t('@.customization-tips.title') }}</a>
- <div>
- <mk-post-form v-if="$store.state.settings.showPostFormOnTopOfTl"/>
- <mk-timeline ref="tl" @loaded="onTlLoaded"/>
- </div>
- </div>
- </template>
- <template v-else>
- <div v-for="place in ['left', 'right']" :class="place">
- <component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp" platform="desktop"/>
- </div>
- <div class="main">
- <mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>
- <mk-timeline class="tl" ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
- </div>
- </template>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import i18n from '../../../i18n';
-import * as XDraggable from 'vuedraggable';
-import * as uuid from 'uuid';
-
-const defaultDesktopHomeWidgets = {
- left: [
- 'profile',
- 'calendar',
- 'activity',
- 'rss',
- 'hashtags',
- 'photo-stream',
- 'version'
- ],
- right: [
- 'broadcast',
- 'notifications',
- 'users',
- 'polls',
- 'server',
- 'nav',
- 'tips'
- ]
-};
-
-//#region Construct home data
-const _defaultDesktopHomeWidgets = [];
-
-for (const widget of defaultDesktopHomeWidgets.left) {
- _defaultDesktopHomeWidgets.push({
- name: widget,
- id: uuid(),
- place: 'left',
- data: {}
- });
-}
-
-for (const widget of defaultDesktopHomeWidgets.right) {
- _defaultDesktopHomeWidgets.push({
- name: widget,
- id: uuid(),
- place: 'right',
- data: {}
- });
-}
-//#endregion
-
-export default Vue.extend({
- i18n: i18n('desktop/views/components/home.vue'),
- components: {
- XDraggable
- },
-
- props: {
- customize: {
- type: Boolean,
- default: false
- },
- mode: {
- type: String,
- default: 'timeline'
- }
- },
-
- data() {
- return {
- connection: null,
- widgetAdderSelected: null,
- trash: []
- };
- },
-
- computed: {
- home(): any[] {
- return this.$store.state.settings.home || [];
- },
- left(): any[] {
- return this.home.filter(w => w.place == 'left');
- },
- right(): any[] {
- return this.home.filter(w => w.place == 'right');
- },
- widgets(): any {
- return {
- left: this.left,
- right: this.right
- };
- }
- },
-
- created() {
- if (this.$store.state.settings.home == null) {
- this.$root.api('i/update_home', {
- home: _defaultDesktopHomeWidgets
- }).then(() => {
- this.$store.commit('settings/setHome', _defaultDesktopHomeWidgets);
- });
- }
- },
-
- mounted() {
- this.connection = this.$root.stream.useSharedConnection('main');
- },
-
- beforeDestroy() {
- this.connection.dispose();
- },
-
- methods: {
- hint() {
- this.$root.dialog({
- title: this.$t('@.customization-tips.title'),
- text: this.$t('@.customization-tips.paragraph')
- });
- },
-
- onTlLoaded() {
- this.$emit('loaded');
- },
-
- onWidgetContextmenu(widgetId) {
- const w = (this.$refs[widgetId] as any)[0];
- if (w.func) w.func();
- },
-
- onWidgetSort() {
- this.saveHome();
- },
-
- onTrash(evt) {
- this.saveHome();
- },
-
- addWidget() {
- this.$store.dispatch('settings/addHomeWidget', {
- name: this.widgetAdderSelected,
- id: uuid(),
- place: 'left',
- data: {}
- });
- },
-
- saveHome() {
- const left = this.widgets.left;
- const right = this.widgets.right;
- this.$store.commit('settings/setHome', left.concat(right));
- for (const w of left) w.place = 'left';
- for (const w of right) w.place = 'right';
- this.$root.api('i/update_home', {
- home: this.home
- });
- },
-
- warp(date) {
- (this.$refs.tl as any).warp(date);
- },
-
- focus() {
- (this.$refs.tl as any).focus();
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.mk-home
- display block
-
- &[data-customize]
- padding-top 48px
- background-image url('/assets/desktop/grid.svg')
-
- > .main > .main
- > a
- display block
- margin-bottom 8px
- text-align center
-
- > div
- cursor not-allowed !important
-
- > *
- pointer-events none
-
- &:not([data-customize])
- > .main > *:empty
- display none
-
- > .customize
- position fixed
- z-index 1000
- top 0
- left 0
- width 100%
- height 48px
- color var(--text)
- background var(--desktopHeaderBg)
- box-shadow 0 1px 1px rgba(#000, 0.075)
-
- > a
- display block
- position absolute
- z-index 1001
- top 0
- right 0
- padding 0 16px
- line-height 48px
- text-decoration none
- color var(--primaryForeground)
- background var(--primary)
- transition background 0.1s ease
-
- &:hover
- background var(--primaryLighten10)
-
- &:active
- background var(--primaryDarken10)
- transition background 0s ease
-
- > [data-icon]
- margin-right 8px
-
- > div
- display flex
- margin 0 auto
- max-width 1220px - 32px
-
- > div
- width 50%
-
- &.adder
- > p
- display inline
- line-height 48px
-
- &.trash
- border-left solid 1px var(--faceDivider)
-
- > div
- width 100%
- height 100%
-
- > p
- position absolute
- top 0
- left 0
- width 100%
- line-height 48px
- margin 0
- text-align center
- pointer-events none
-
- > .main
- display flex
- justify-content center
- margin 0 auto
- max-width 1240px
-
- > *
- .customize-container
- cursor move
- border-radius 6px
-
- &:hover
- box-shadow 0 0 8px rgba(64, 120, 200, 0.3)
-
- > *
- pointer-events none
-
- > .main
- padding 16px
- width calc(100% - 280px * 2)
- order 2
-
- > .form
- margin-bottom 16px
- box-shadow var(--shadow)
- border-radius var(--round)
-
- &.side
- > .main
- width calc(100% - 280px)
- max-width 680px
-
- > *:not(.main)
- width 280px
- padding 16px 0 16px 0
-
- > *:not(:last-child)
- margin-bottom 16px
-
- > .left
- padding-left 16px
- order 1
-
- > .right
- padding-right 16px
- order 3
-
- &.side
- @media (max-width 1000px)
- > *:not(.main)
- display none
-
- > .main
- width 100%
- max-width 700px
- margin 0 auto
-
- &:not(.side)
- @media (max-width 1200px)
- > *:not(.main)
- display none
-
- > .main
- width 100%
- max-width 700px
- margin 0 auto
-
-</style>
diff --git a/src/client/app/desktop/views/components/index.ts b/src/client/app/desktop/views/components/index.ts
index 2edc8117a8..0bc6fa9af4 100644
--- a/src/client/app/desktop/views/components/index.ts
+++ b/src/client/app/desktop/views/components/index.ts
@@ -2,8 +2,6 @@ import Vue from 'vue';
import ui from './ui.vue';
import uiNotification from './ui-notification.vue';
-import home from './home.vue';
-import timeline from './timeline.vue';
import notes from './notes.vue';
import subNoteContent from './sub-note-content.vue';
import window from './window.vue';
@@ -24,8 +22,6 @@ import widgetContainer from './widget-container.vue';
Vue.component('mk-ui', ui);
Vue.component('mk-ui-notification', uiNotification);
-Vue.component('mk-home', home);
-Vue.component('mk-timeline', timeline);
Vue.component('mk-notes', notes);
Vue.component('mk-sub-note-content', subNoteContent);
Vue.component('mk-window', window);
diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue
index 3452122b9a..e4e7830a16 100644
--- a/src/client/app/desktop/views/components/settings.vue
+++ b/src/client/app/desktop/views/components/settings.vue
@@ -31,9 +31,6 @@
<ui-switch v-model="autoPopout">{{ $t('auto-popout') }}
<span slot="desc">{{ $t('auto-popout-desc') }}</span>
</ui-switch>
- <ui-switch v-model="deckNav">{{ $t('deck-nav') }}
- <span slot="desc">{{ $t('deck-nav-desc') }}</span>
- </ui-switch>
<ui-switch v-model="keepCw">{{ $t('keep-cw') }}
<span slot="desc">{{ $t('keep-cw-desc') }}</span>
</ui-switch>
@@ -90,9 +87,6 @@
<ui-radio v-model="navbar" value="right">{{ $t('navbar-position-right') }}</ui-radio>
</section>
<section>
- <ui-switch v-model="deckDefault">{{ $t('deck-default') }}</ui-switch>
- </section>
- <section>
<ui-switch v-model="darkmode">{{ $t('dark-mode') }}</ui-switch>
<ui-switch v-model="useShadow">{{ $t('use-shadow') }}</ui-switch>
<ui-switch v-model="roundedCorners">{{ $t('rounded-corners') }}</ui-switch>
@@ -337,11 +331,6 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
},
- deckNav: {
- get() { return this.$store.state.settings.deckNav; },
- set(value) { this.$store.commit('settings/set', { key: 'deckNav', value }); }
- },
-
keepCw: {
get() { return this.$store.state.settings.keepCw; },
set(value) { this.$store.commit('settings/set', { key: 'keepCw', value }); }
@@ -367,11 +356,6 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'deckColumnWidth', value }); }
},
- deckDefault: {
- get() { return this.$store.state.device.deckDefault; },
- set(value) { this.$store.commit('device/set', { key: 'deckDefault', value }); }
- },
-
enableSounds: {
get() { return this.$store.state.device.enableSounds; },
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
@@ -534,8 +518,7 @@ export default Vue.extend({
},
methods: {
customizeHome() {
- this.$router.push('/i/customize-home');
- this.$emit('done');
+ location.href = '/?customize';
},
updateWallpaper() {
this.$chooseDriveFile({
diff --git a/src/client/app/desktop/views/components/ui.header.account.vue b/src/client/app/desktop/views/components/ui.header.account.vue
index bc7a8b2231..4a3cc71548 100644
--- a/src/client/app/desktop/views/components/ui.header.account.vue
+++ b/src/client/app/desktop/views/components/ui.header.account.vue
@@ -45,13 +45,6 @@
</ul>
<ul>
<li>
- <router-link to="/i/customize-home">
- <i><fa icon="wrench"/></i>
- <span>{{ $t('customize') }}</span>
- <i><fa icon="angle-right"/></i>
- </router-link>
- </li>
- <li>
<router-link to="/i/settings">
<i><fa icon="cog"/></i>
<span>{{ $t('settings') }}</span>
diff --git a/src/client/app/desktop/views/components/ui.header.nav.vue b/src/client/app/desktop/views/components/ui.header.nav.vue
index 8e78829de3..44659eb0d8 100644
--- a/src/client/app/desktop/views/components/ui.header.nav.vue
+++ b/src/client/app/desktop/views/components/ui.header.nav.vue
@@ -2,20 +2,20 @@
<div class="nav">
<ul>
<template v-if="$store.getters.isSignedIn">
- <template v-if="$store.state.device.deckDefault">
- <li class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
+ <template v-if="$store.state.device.deckMode">
+ <li class="deck active" @click="goToTop">
<router-link to="/"><fa icon="columns"/><p>{{ $t('deck') }}</p></router-link>
</li>
- <li class="home" :class="{ active: $route.name == 'home' }" @click="goToTop">
- <router-link to="/home"><fa icon="home"/><p>{{ $t('home') }}</p></router-link>
+ <li class="home">
+ <a @click="toggleDeckMode(false)"><fa icon="home"/><p>{{ $t('home') }}</p></a>
</li>
</template>
<template v-else>
- <li class="home" :class="{ active: $route.name == 'home' || $route.name == 'index' }" @click="goToTop">
+ <li class="home active" @click="goToTop">
<router-link to="/"><fa icon="home"/><p>{{ $t('home') }}</p></router-link>
</li>
- <li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
- <router-link to="/deck"><fa icon="columns"/><p>{{ $t('deck') }}</p></router-link>
+ <li class="deck">
+ <a @click="toggleDeckMode(true)"><fa icon="columns"/><p>{{ $t('deck') }}</p></a>
</li>
</template>
<li class="messaging">
@@ -70,6 +70,11 @@ export default Vue.extend({
}
},
methods: {
+ toggleDeckMode(deck) {
+ this.$store.commit('device/set', { key: 'deckMode', value: deck });
+ location.reload();
+ },
+
onReversiInvited() {
this.hasGameInvitations = true;
},
diff --git a/src/client/app/desktop/views/components/ui.sidebar.vue b/src/client/app/desktop/views/components/ui.sidebar.vue
index 8b5f14290c..ec6b056595 100644
--- a/src/client/app/desktop/views/components/ui.sidebar.vue
+++ b/src/client/app/desktop/views/components/ui.sidebar.vue
@@ -6,7 +6,7 @@
</div>
<div class="nav" v-if="$store.getters.isSignedIn">
- <template v-if="$store.state.device.deckDefault">
+ <template v-if="$store.state.device.deckMode">
<div class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
<router-link to="/"><fa icon="columns"/></router-link>
</div>
diff --git a/src/client/app/desktop/views/pages/deck/deck.column-core.vue b/src/client/app/desktop/views/deck/deck.column-core.vue
index 974c58235d..974c58235d 100644
--- a/src/client/app/desktop/views/pages/deck/deck.column-core.vue
+++ b/src/client/app/desktop/views/deck/deck.column-core.vue
diff --git a/src/client/app/desktop/views/pages/deck/deck.column.vue b/src/client/app/desktop/views/deck/deck.column.vue
index 2acd2d0eda..f731e2e9b1 100644
--- a/src/client/app/desktop/views/pages/deck/deck.column.vue
+++ b/src/client/app/desktop/views/deck/deck.column.vue
@@ -27,9 +27,9 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
-import Menu from '../../../../common/views/components/menu.vue';
-import { countIf } from '../../../../../../prelude/array';
+import i18n from '../../../i18n';
+import Menu from '../../../common/views/components/menu.vue';
+import { countIf } from '../../../../../prelude/array';
export default Vue.extend({
i18n: i18n('deck'),
@@ -245,10 +245,7 @@ export default Vue.extend({
},
close() {
- this.$store.commit('device/set', {
- key: 'deckTemporaryColumn',
- value: null
- });
+ this.$router.push('/');
},
goTop() {
diff --git a/src/client/app/desktop/views/pages/deck/deck.direct-column.vue b/src/client/app/desktop/views/deck/deck.direct-column.vue
index cdeba95f5f..a1acf4e7f7 100644
--- a/src/client/app/desktop/views/pages/deck/deck.direct-column.vue
+++ b/src/client/app/desktop/views/deck/deck.direct-column.vue
@@ -8,7 +8,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import XDirect from './deck.direct.vue';
diff --git a/src/client/app/desktop/views/pages/deck/deck.direct.vue b/src/client/app/desktop/views/deck/deck.direct.vue
index c6c2b99233..c6c2b99233 100644
--- a/src/client/app/desktop/views/pages/deck/deck.direct.vue
+++ b/src/client/app/desktop/views/deck/deck.direct.vue
diff --git a/src/client/app/desktop/views/deck/deck.favorites-column.vue b/src/client/app/desktop/views/deck/deck.favorites-column.vue
new file mode 100644
index 0000000000..3c2b50dee8
--- /dev/null
+++ b/src/client/app/desktop/views/deck/deck.favorites-column.vue
@@ -0,0 +1,88 @@
+<template>
+<x-column>
+ <span slot="header">
+ <fa :icon="['fa', 'star']"/>{{ $t('favorites') }}
+ </span>
+
+ <div>
+ <x-notes ref="timeline" :more="existMore ? more : null"/>
+ </div>
+</x-column>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../../i18n';
+import XColumn from './deck.column.vue';
+import XNotes from './deck.notes.vue';
+
+const fetchLimit = 10;
+
+export default Vue.extend({
+ i18n: i18n(),
+
+ components: {
+ XColumn,
+ XNotes,
+ },
+
+ data() {
+ return {
+ fetching: true,
+ moreFetching: false,
+ existMore: false,
+ };
+ },
+
+ mounted() {
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ this.fetching = true;
+
+ (this.$refs.timeline as any).init(() => new Promise((res, rej) => {
+ this.$root.api('i/favorites', {
+ limit: fetchLimit + 1,
+ }).then(notes => {
+ if (notes.length == fetchLimit + 1) {
+ notes.pop();
+ this.existMore = true;
+ }
+ res(notes.map(x => x.note));
+ this.fetching = false;
+ this.$emit('loaded');
+ }, rej);
+ }));
+ },
+
+ more() {
+ this.moreFetching = true;
+
+ const promise = this.$root.api('i/favorites', {
+ limit: fetchLimit + 1,
+ untilId: (this.$refs.timeline as any).tail().id,
+ });
+
+ promise.then(notes => {
+ if (notes.length == fetchLimit + 1) {
+ notes.pop();
+ } else {
+ this.existMore = false;
+ }
+ for (const n of notes) {
+ (this.$refs.timeline as any).append(n);
+ }
+ this.moreFetching = false;
+ });
+
+ return promise;
+ },
+
+ focus() {
+ this.$refs.timeline.focus();
+ }
+ }
+});
+</script>
diff --git a/src/client/app/desktop/views/deck/deck.hashtag-column.vue b/src/client/app/desktop/views/deck/deck.hashtag-column.vue
new file mode 100644
index 0000000000..ca2d8cdb8d
--- /dev/null
+++ b/src/client/app/desktop/views/deck/deck.hashtag-column.vue
@@ -0,0 +1,119 @@
+<template>
+<x-column>
+ <span slot="header">
+ <fa icon="hashtag"/><span>{{ tag }}</span>
+ </span>
+
+ <div class="xroyrflcmhhtmlwmyiwpfqiirqokfueb">
+ <div ref="chart" class="chart"></div>
+ <x-hashtag-tl :tag-tl="tagTl" class="tl"/>
+ </div>
+</x-column>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import XColumn from './deck.column.vue';
+import XHashtagTl from './deck.hashtag-tl.vue';
+import ApexCharts from 'apexcharts';
+
+export default Vue.extend({
+ components: {
+ XColumn,
+ XHashtagTl
+ },
+
+ computed: {
+ tag(): string {
+ return this.$route.params.tag;
+ },
+
+ tagTl(): any {
+ return {
+ query: [[this.tag]]
+ };
+ }
+ },
+
+ watch: {
+ $route: 'fetch'
+ },
+
+ created() {
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ this.$root.api('charts/hashtag', {
+ tag: this.tag,
+ span: 'hour',
+ limit: 24
+ }).then(stats => {
+ const local = [];
+ const remote = [];
+
+ const now = new Date();
+ const y = now.getFullYear();
+ const m = now.getMonth();
+ const d = now.getDate();
+ const h = now.getHours();
+
+ for (let i = 0; i < 24; i++) {
+ const x = new Date(y, m, d, h - i);
+ local.push([x, stats.local.count[i]]);
+ remote.push([x, stats.remote.count[i]]);
+ }
+
+ const chart = new ApexCharts(this.$refs.chart, {
+ chart: {
+ type: 'area',
+ height: 70,
+ sparkline: {
+ enabled: true
+ },
+ },
+ grid: {
+ clipMarkers: false,
+ padding: {
+ top: 16,
+ right: 16,
+ bottom: 16,
+ left: 16
+ }
+ },
+ stroke: {
+ curve: 'straight',
+ width: 2
+ },
+ series: [{
+ name: 'Local',
+ data: local
+ }, {
+ name: 'Remote',
+ data: remote
+ }],
+ xaxis: {
+ type: 'datetime',
+ }
+ });
+
+ chart.render();
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.xroyrflcmhhtmlwmyiwpfqiirqokfueb
+ background var(--deckColumnBg)
+
+ > .chart
+ margin-bottom 16px
+ background var(--face)
+
+ > .tl
+ background var(--face)
+
+</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.hashtag-tl.vue b/src/client/app/desktop/views/deck/deck.hashtag-tl.vue
index 9a70733fda..9a70733fda 100644
--- a/src/client/app/desktop/views/pages/deck/deck.hashtag-tl.vue
+++ b/src/client/app/desktop/views/deck/deck.hashtag-tl.vue
diff --git a/src/client/app/desktop/views/pages/deck/deck.list-tl.vue b/src/client/app/desktop/views/deck/deck.list-tl.vue
index 68fbbb3ff9..68fbbb3ff9 100644
--- a/src/client/app/desktop/views/pages/deck/deck.list-tl.vue
+++ b/src/client/app/desktop/views/deck/deck.list-tl.vue
diff --git a/src/client/app/desktop/views/pages/deck/deck.mentions-column.vue b/src/client/app/desktop/views/deck/deck.mentions-column.vue
index 011a321c3a..1fce65ea70 100644
--- a/src/client/app/desktop/views/pages/deck/deck.mentions-column.vue
+++ b/src/client/app/desktop/views/deck/deck.mentions-column.vue
@@ -8,7 +8,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import XMentions from './deck.mentions.vue';
diff --git a/src/client/app/desktop/views/pages/deck/deck.mentions.vue b/src/client/app/desktop/views/deck/deck.mentions.vue
index 5fcabde5d6..5fcabde5d6 100644
--- a/src/client/app/desktop/views/pages/deck/deck.mentions.vue
+++ b/src/client/app/desktop/views/deck/deck.mentions.vue
diff --git a/src/client/app/desktop/views/pages/deck/deck.note-column.vue b/src/client/app/desktop/views/deck/deck.note-column.vue
index 74da48bffc..f365573538 100644
--- a/src/client/app/desktop/views/pages/deck/deck.note-column.vue
+++ b/src/client/app/desktop/views/deck/deck.note-column.vue
@@ -18,10 +18,10 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import XNotes from './deck.notes.vue';
-import XNote from '../../components/note.vue';
+import XNote from '../components/note.vue';
export default Vue.extend({
i18n: i18n(),
@@ -31,13 +31,6 @@ export default Vue.extend({
XNote
},
- props: {
- noteId: {
- type: String,
- required: true
- }
- },
-
data() {
return {
note: null,
@@ -45,11 +38,25 @@ export default Vue.extend({
};
},
+ watch: {
+ $route: 'fetch'
+ },
+
created() {
- this.$root.api('notes/show', { noteId: this.noteId }).then(note => {
- this.note = note;
- this.fetching = false;
- });
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ this.fetching = true;
+
+ this.$root.api('notes/show', {
+ noteId: this.$route.params.note
+ }).then(note => {
+ this.note = note;
+ this.fetching = false;
+ });
+ }
}
});
</script>
diff --git a/src/client/app/desktop/views/pages/deck/deck.notes.vue b/src/client/app/desktop/views/deck/deck.notes.vue
index 54e01a0012..260d75a884 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notes.vue
+++ b/src/client/app/desktop/views/deck/deck.notes.vue
@@ -38,10 +38,10 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
-import shouldMuteNote from '../../../../common/scripts/should-mute-note';
+import i18n from '../../../i18n';
+import shouldMuteNote from '../../../common/scripts/should-mute-note';
-import XNote from '../../components/note.vue';
+import XNote from '../components/note.vue';
const displayLimit = 20;
diff --git a/src/client/app/desktop/views/pages/deck/deck.notification.vue b/src/client/app/desktop/views/deck/deck.notification.vue
index c20fe87a4f..56915f2d9c 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notification.vue
+++ b/src/client/app/desktop/views/deck/deck.notification.vue
@@ -96,8 +96,8 @@
<script lang="ts">
import Vue from 'vue';
-import getNoteSummary from '../../../../../../misc/get-note-summary';
-import XNote from '../../components/note.vue';
+import getNoteSummary from '../../../../../misc/get-note-summary';
+import XNote from '../components/note.vue';
export default Vue.extend({
components: {
diff --git a/src/client/app/desktop/views/pages/deck/deck.notifications-column.vue b/src/client/app/desktop/views/deck/deck.notifications-column.vue
index 69da7919b6..00bf77cf89 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notifications-column.vue
+++ b/src/client/app/desktop/views/deck/deck.notifications-column.vue
@@ -8,7 +8,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import XNotifications from './deck.notifications.vue';
diff --git a/src/client/app/desktop/views/pages/deck/deck.notifications.vue b/src/client/app/desktop/views/deck/deck.notifications.vue
index 5b556b31c8..5130140685 100644
--- a/src/client/app/desktop/views/pages/deck/deck.notifications.vue
+++ b/src/client/app/desktop/views/deck/deck.notifications.vue
@@ -25,7 +25,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XNotification from './deck.notification.vue';
const displayLimit = 20;
diff --git a/src/client/app/desktop/views/pages/deck/deck.tl-column.vue b/src/client/app/desktop/views/deck/deck.tl-column.vue
index bc5e045373..1dac733718 100644
--- a/src/client/app/desktop/views/pages/deck/deck.tl-column.vue
+++ b/src/client/app/desktop/views/deck/deck.tl-column.vue
@@ -38,7 +38,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import XTl from './deck.tl.vue';
import XListTl from './deck.list-tl.vue';
diff --git a/src/client/app/desktop/views/pages/deck/deck.tl.vue b/src/client/app/desktop/views/deck/deck.tl.vue
index 4f5e3af197..4f5e3af197 100644
--- a/src/client/app/desktop/views/pages/deck/deck.tl.vue
+++ b/src/client/app/desktop/views/deck/deck.tl.vue
diff --git a/src/client/app/desktop/views/pages/deck/deck.user-column.vue b/src/client/app/desktop/views/deck/deck.user-column.vue
index b3e92f3e8a..60b3d2f0d5 100644
--- a/src/client/app/desktop/views/pages/deck/deck.user-column.vue
+++ b/src/client/app/desktop/views/deck/deck.user-column.vue
@@ -93,13 +93,13 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
-import parseAcct from '../../../../../../misc/acct/parse';
+import i18n from '../../../i18n';
+import parseAcct from '../../../../../misc/acct/parse';
import XColumn from './deck.column.vue';
import XNotes from './deck.notes.vue';
-import XNote from '../../components/note.vue';
-import XUserMenu from '../../../../common/views/components/user-menu.vue';
-import { concat } from '../../../../../../prelude/array';
+import XNote from '../components/note.vue';
+import XUserMenu from '../../../common/views/components/user-menu.vue';
+import { concat } from '../../../../../prelude/array';
import ApexCharts from 'apexcharts';
const fetchLimit = 10;
@@ -112,13 +112,6 @@ export default Vue.extend({
XNote
},
- props: {
- acct: {
- type: String,
- required: true
- }
- },
-
data() {
return {
user: null,
@@ -144,119 +137,128 @@ export default Vue.extend({
},
},
+ watch: {
+ $route: 'fetch'
+ },
+
created() {
- this.$root.api('users/show', parseAcct(this.acct)).then(user => {
- this.user = user;
- this.fetching = false;
+ this.fetch();
+ },
- this.$nextTick(() => {
- (this.$refs.timeline as any).init(() => this.initTl());
- });
+ methods: {
+ fetch() {
+ this.fetching = true;
+ this.$root.api('users/show', parseAcct(this.$route.params.user)).then(user => {
+ this.user = user;
+ this.fetching = false;
- const image = [
- 'image/jpeg',
- 'image/png',
- 'image/gif'
- ];
+ this.$nextTick(() => {
+ (this.$refs.timeline as any).init(() => this.initTl());
+ });
- this.$root.api('users/notes', {
- userId: this.user.id,
- fileType: image,
- excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
- limit: 9,
- untilDate: new Date().getTime() + 1000 * 86400 * 365
- }).then(notes => {
- for (const note of notes) {
- for (const file of note.files) {
- file._note = note;
+ const image = [
+ 'image/jpeg',
+ 'image/png',
+ 'image/gif'
+ ];
+
+ this.$root.api('users/notes', {
+ userId: this.user.id,
+ fileType: image,
+ excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
+ limit: 9,
+ untilDate: new Date().getTime() + 1000 * 86400 * 365
+ }).then(notes => {
+ for (const note of notes) {
+ for (const file of note.files) {
+ file._note = note;
+ }
}
- }
- const files = concat(notes.map((n: any): any[] => n.files));
- this.images = files.filter(f => image.includes(f.type)).slice(0, 9);
- });
+ const files = concat(notes.map((n: any): any[] => n.files));
+ this.images = files.filter(f => image.includes(f.type)).slice(0, 9);
+ });
- this.$root.api('charts/user/notes', {
- userId: this.user.id,
- span: 'day',
- limit: 21
- }).then(stats => {
- const normal = [];
- const reply = [];
- const renote = [];
+ this.$root.api('charts/user/notes', {
+ userId: this.user.id,
+ span: 'day',
+ limit: 21
+ }).then(stats => {
+ const normal = [];
+ const reply = [];
+ const renote = [];
- const now = new Date();
- const y = now.getFullYear();
- const m = now.getMonth();
- const d = now.getDate();
+ const now = new Date();
+ const y = now.getFullYear();
+ const m = now.getMonth();
+ const d = now.getDate();
- for (let i = 0; i < 21; i++) {
- const x = new Date(y, m, d - i);
- normal.push([
- x,
- stats.diffs.normal[i]
- ]);
- reply.push([
- x,
- stats.diffs.reply[i]
- ]);
- renote.push([
- x,
- stats.diffs.renote[i]
- ]);
- }
+ for (let i = 0; i < 21; i++) {
+ const x = new Date(y, m, d - i);
+ normal.push([
+ x,
+ stats.diffs.normal[i]
+ ]);
+ reply.push([
+ x,
+ stats.diffs.reply[i]
+ ]);
+ renote.push([
+ x,
+ stats.diffs.renote[i]
+ ]);
+ }
- const chart = new ApexCharts(this.$refs.chart, {
- chart: {
- type: 'bar',
- stacked: true,
- height: 100,
- sparkline: {
- enabled: true
+ const chart = new ApexCharts(this.$refs.chart, {
+ chart: {
+ type: 'bar',
+ stacked: true,
+ height: 100,
+ sparkline: {
+ enabled: true
+ },
},
- },
- plotOptions: {
- bar: {
- columnWidth: '90%'
- }
- },
- grid: {
- clipMarkers: false,
- padding: {
- top: 16,
- right: 16,
- bottom: 16,
- left: 16
- }
- },
- tooltip: {
- shared: true,
- intersect: false
- },
- series: [{
- name: 'Normal',
- data: normal
- }, {
- name: 'Reply',
- data: reply
- }, {
- name: 'Renote',
- data: renote
- }],
- xaxis: {
- type: 'datetime',
- crosshairs: {
- width: 1,
- opacity: 1
+ plotOptions: {
+ bar: {
+ columnWidth: '90%'
+ }
+ },
+ grid: {
+ clipMarkers: false,
+ padding: {
+ top: 16,
+ right: 16,
+ bottom: 16,
+ left: 16
+ }
+ },
+ tooltip: {
+ shared: true,
+ intersect: false
+ },
+ series: [{
+ name: 'Normal',
+ data: normal
+ }, {
+ name: 'Reply',
+ data: reply
+ }, {
+ name: 'Renote',
+ data: renote
+ }],
+ xaxis: {
+ type: 'datetime',
+ crosshairs: {
+ width: 1,
+ opacity: 1
+ }
}
- }
- });
+ });
- chart.render();
+ chart.render();
+ });
});
- });
- },
+ },
- methods: {
initTl() {
return new Promise((res, rej) => {
this.$root.api('users/notes', {
diff --git a/src/client/app/desktop/views/pages/deck/deck.vue b/src/client/app/desktop/views/deck/deck.vue
index 30b985e7e4..5af2075e4a 100644
--- a/src/client/app/desktop/views/pages/deck/deck.vue
+++ b/src/client/app/desktop/views/deck/deck.vue
@@ -9,11 +9,7 @@
</div>
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])" @parentFocus="moveFocus(ids[0], $event)"/>
</template>
- <template v-if="temporaryColumn">
- <x-user-column v-if="temporaryColumn.type == 'user'" :acct="temporaryColumn.acct" :key="temporaryColumn.acct"/>
- <x-note-column v-else-if="temporaryColumn.type == 'note'" :note-id="temporaryColumn.noteId" :key="temporaryColumn.noteId"/>
- <x-hashtag-column v-else-if="temporaryColumn.type == 'tag'" :tag="temporaryColumn.tag" :key="temporaryColumn.tag"/>
- </template>
+ <router-view></router-view>
<button ref="add" @click="add" :title="$t('@deck.add-column')"><fa icon="plus"/></button>
</div>
</mk-ui>
@@ -21,20 +17,17 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumnCore from './deck.column-core.vue';
-import Menu from '../../../../common/views/components/menu.vue';
-import MkUserListsWindow from '../../components/user-lists-window.vue';
+import Menu from '../../../common/views/components/menu.vue';
+import MkUserListsWindow from '../components/user-lists-window.vue';
import * as uuid from 'uuid';
export default Vue.extend({
i18n: i18n('deck'),
components: {
- XColumnCore,
- XUserColumn: () => import('./deck.user-column.vue').then(m => m.default),
- XNoteColumn: () => import('./deck.note-column.vue').then(m => m.default),
- XHashtagColumn: () => import('./deck.hashtag-column.vue').then(m => m.default)
+ XColumnCore
},
computed: {
@@ -55,10 +48,6 @@ export default Vue.extend({
};
},
- temporaryColumn(): any {
- return this.$store.state.device.deckTemporaryColumn;
- },
-
keymap(): any {
return {
't': this.focus
@@ -66,7 +55,7 @@ export default Vue.extend({
}
},
- watch: {
+ watch: {/*
temporaryColumn() {
if (this.temporaryColumn != null) {
this.$nextTick(() => {
@@ -76,7 +65,7 @@ export default Vue.extend({
});
});
}
- }
+ }*/
},
provide() {
@@ -86,8 +75,6 @@ export default Vue.extend({
},
created() {
- this.$store.commit('navHook', this.onNav);
-
if (this.$store.state.settings.deck == null) {
const deck = {
columns: [/*{
@@ -133,8 +120,6 @@ export default Vue.extend({
},
beforeDestroy() {
- this.$store.commit('navHook', null);
-
document.documentElement.style.overflow = 'auto';
},
@@ -143,39 +128,6 @@ export default Vue.extend({
return this.$refs[id][0];
},
- onNav(to) {
- if (!this.$store.state.settings.deckNav) return false;
-
- if (to.name == 'user') {
- this.$store.commit('device/set', {
- key: 'deckTemporaryColumn',
- value: {
- type: 'user',
- acct: to.params.user
- }
- });
- return true;
- } else if (to.name == 'note') {
- this.$store.commit('device/set', {
- key: 'deckTemporaryColumn',
- value: {
- type: 'note',
- noteId: to.params.note
- }
- });
- return true;
- } else if (to.name == 'tag') {
- this.$store.commit('device/set', {
- key: 'deckTemporaryColumn',
- value: {
- type: 'tag',
- tag: to.params.tag
- }
- });
- return true;
- }
- },
-
add() {
this.$root.new(Menu, {
source: this.$refs.add,
diff --git a/src/client/app/desktop/views/pages/deck/deck.widgets-column.vue b/src/client/app/desktop/views/deck/deck.widgets-column.vue
index 0798e2ccc7..2af2f1f05c 100644
--- a/src/client/app/desktop/views/pages/deck/deck.widgets-column.vue
+++ b/src/client/app/desktop/views/deck/deck.widgets-column.vue
@@ -50,7 +50,7 @@
<script lang="ts">
import Vue from 'vue';
-import i18n from '../../../../i18n';
+import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import * as XDraggable from 'vuedraggable';
import * as uuid from 'uuid';
diff --git a/src/client/app/desktop/views/pages/favorites.vue b/src/client/app/desktop/views/home/favorites.vue
index 066ce3f53c..4a4fc9ad8f 100644
--- a/src/client/app/desktop/views/pages/favorites.vue
+++ b/src/client/app/desktop/views/home/favorites.vue
@@ -1,16 +1,14 @@
<template>
-<mk-ui>
- <main v-if="!fetching">
- <sequential-entrance animation="entranceFromTop" delay="25">
- <template v-for="favorite in favorites">
- <mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
- </template>
- </sequential-entrance>
- <div class="more" v-if="existMore">
- <ui-button inline @click="more">{{ $t('@.load-more') }}</ui-button>
- </div>
- </main>
-</mk-ui>
+<div class="ecsvsegy" v-if="!fetching">
+ <sequential-entrance animation="entranceFromTop" delay="25">
+ <template v-for="favorite in favorites">
+ <mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
+ </template>
+ </sequential-entrance>
+ <div class="more" v-if="existMore">
+ <ui-button inline @click="more">{{ $t('@.load-more') }}</ui-button>
+ </div>
+</div>
</template>
<script lang="ts">
@@ -72,10 +70,8 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
-main
+.ecsvsegy
margin 0 auto
- padding 16px
- max-width 700px
> * > .post
margin-bottom 16px
diff --git a/src/client/app/desktop/views/home/home.vue b/src/client/app/desktop/views/home/home.vue
new file mode 100644
index 0000000000..5e265634fb
--- /dev/null
+++ b/src/client/app/desktop/views/home/home.vue
@@ -0,0 +1,400 @@
+<template>
+<component :is="customize ? 'mk-dummy' : 'mk-ui'" v-hotkey.global="keymap" v-if="$store.getters.isSignedIn || $route.name != 'index'">
+ <div class="wqsofvpm" :data-customize="customize">
+ <div class="customize" v-if="customize">
+ <a @click="done()"><fa icon="check"/>{{ $t('done') }}</a>
+ <div>
+ <div class="adder">
+ <p>{{ $t('add-widget') }}</p>
+ <select v-model="widgetAdderSelected">
+ <option value="profile">{{ $t('@.widgets.profile') }}</option>
+ <option value="analog-clock">{{ $t('@.widgets.analog-clock') }}</option>
+ <option value="calendar">{{ $t('@.widgets.calendar') }}</option>
+ <option value="timemachine">{{ $t('@.widgets.timemachine') }}</option>
+ <option value="activity">{{ $t('@.widgets.activity') }}</option>
+ <option value="rss">{{ $t('@.widgets.rss') }}</option>
+ <option value="trends">{{ $t('@.widgets.trends') }}</option>
+ <option value="photo-stream">{{ $t('@.widgets.photo-stream') }}</option>
+ <option value="slideshow">{{ $t('@.widgets.slideshow') }}</option>
+ <option value="version">{{ $t('@.widgets.version') }}</option>
+ <option value="broadcast">{{ $t('@.widgets.broadcast') }}</option>
+ <option value="notifications">{{ $t('@.widgets.notifications') }}</option>
+ <option value="users">{{ $t('@.widgets.users') }}</option>
+ <option value="polls">{{ $t('@.widgets.polls') }}</option>
+ <option value="post-form">{{ $t('@.widgets.post-form') }}</option>
+ <option value="messaging">{{ $t('@.widgets.messaging') }}</option>
+ <option value="memo">{{ $t('@.widgets.memo') }}</option>
+ <option value="hashtags">{{ $t('@.widgets.hashtags') }}</option>
+ <option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option>
+ <option value="server">{{ $t('@.widgets.server') }}</option>
+ <option value="nav">{{ $t('@.widgets.nav') }}</option>
+ <option value="tips">{{ $t('@.widgets.tips') }}</option>
+ </select>
+ <button @click="addWidget">{{ $t('add') }}</button>
+ </div>
+ <div class="trash">
+ <x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable>
+ <p>{{ $t('@.trash') }}</p>
+ </div>
+ </div>
+ </div>
+ <div class="main" :class="{ side: widgets.left.length == 0 || widgets.right.length == 0 }">
+ <template v-if="customize">
+ <x-draggable v-for="place in ['left', 'right']"
+ :list="widgets[place]"
+ :class="place"
+ :data-place="place"
+ :options="{ group: 'x', animation: 150 }"
+ @sort="onWidgetSort"
+ :key="place"
+ >
+ <div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
+ <component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
+ </div>
+ </x-draggable>
+ <div class="main">
+ <a @click="hint">{{ $t('@.customization-tips.title') }}</a>
+ <div>
+ <x-timeline/>
+ </div>
+ </div>
+ </template>
+ <template v-else>
+ <div v-for="place in ['left', 'right']" :class="place">
+ <component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="desktop"/>
+ </div>
+ <div class="main">
+ <router-view ref="content"></router-view>
+ </div>
+ </template>
+ </div>
+ </div>
+</component>
+<x-welcome v-else/>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../../i18n';
+import * as XDraggable from 'vuedraggable';
+import * as uuid from 'uuid';
+import XWelcome from '../pages/welcome.vue';
+
+export default Vue.extend({
+ i18n: i18n('desktop/views/components/home.vue'),
+ components: {
+ XDraggable,
+ XWelcome
+ },
+
+ data() {
+ return {
+ customize: window.location.search == '?customize',
+ connection: null,
+ widgetAdderSelected: null,
+ trash: [],
+ view: null
+ };
+ },
+
+ computed: {
+ home(): any[] {
+ if (this.$store.getters.isSignedIn) {
+ return this.$store.state.settings.home || [];
+ } else {
+ return [{
+ name: 'instance',
+ place: 'right'
+ }];
+ }
+ },
+ left(): any[] {
+ return this.home.filter(w => w.place == 'left');
+ },
+ right(): any[] {
+ return this.home.filter(w => w.place == 'right');
+ },
+ widgets(): any {
+ return {
+ left: this.left,
+ right: this.right
+ };
+ },
+ keymap(): any {
+ return {
+ 't': this.focus
+ };
+ }
+ },
+
+ created() {
+ if (this.$store.getters.isSignedIn) {
+ const defaultDesktopHomeWidgets = {
+ left: [
+ 'profile',
+ 'calendar',
+ 'activity',
+ 'rss',
+ 'hashtags',
+ 'photo-stream',
+ 'version'
+ ],
+ right: [
+ 'customize',
+ 'broadcast',
+ 'notifications',
+ 'users',
+ 'polls',
+ 'server',
+ 'nav',
+ 'tips'
+ ]
+ };
+
+ //#region Construct home data
+ const _defaultDesktopHomeWidgets = [];
+
+ for (const widget of defaultDesktopHomeWidgets.left) {
+ _defaultDesktopHomeWidgets.push({
+ name: widget,
+ id: uuid(),
+ place: 'left',
+ data: {}
+ });
+ }
+
+ for (const widget of defaultDesktopHomeWidgets.right) {
+ _defaultDesktopHomeWidgets.push({
+ name: widget,
+ id: uuid(),
+ place: 'right',
+ data: {}
+ });
+ }
+ //#endregion
+
+ if (this.$store.state.settings.home == null) {
+ this.$root.api('i/update_home', {
+ home: _defaultDesktopHomeWidgets
+ }).then(() => {
+ this.$store.commit('settings/setHome', _defaultDesktopHomeWidgets);
+ });
+ }
+ }
+ },
+
+ mounted() {
+ this.connection = this.$root.stream.useSharedConnection('main');
+ },
+
+ beforeDestroy() {
+ this.connection.dispose();
+ },
+
+ methods: {
+ hint() {
+ this.$root.dialog({
+ title: this.$t('@.customization-tips.title'),
+ text: this.$t('@.customization-tips.paragraph')
+ });
+ },
+
+ onTlLoaded() {
+ this.$emit('loaded');
+ },
+
+ onWidgetContextmenu(widgetId) {
+ const w = (this.$refs[widgetId] as any)[0];
+ if (w.func) w.func();
+ },
+
+ onWidgetSort() {
+ this.saveHome();
+ },
+
+ onTrash(evt) {
+ this.saveHome();
+ },
+
+ addWidget() {
+ this.$store.dispatch('settings/addHomeWidget', {
+ name: this.widgetAdderSelected,
+ id: uuid(),
+ place: 'left',
+ data: {}
+ });
+ },
+
+ saveHome() {
+ const left = this.widgets.left;
+ const right = this.widgets.right;
+ this.$store.commit('settings/setHome', left.concat(right));
+ for (const w of left) w.place = 'left';
+ for (const w of right) w.place = 'right';
+ this.$root.api('i/update_home', {
+ home: this.home
+ });
+ },
+
+ done() {
+ location.href = '/';
+ },
+
+ focus() {
+ (this.$refs.content as any).focus();
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.wqsofvpm
+ display block
+
+ &[data-customize]
+ padding-top 48px
+ background-image url('/assets/desktop/grid.svg')
+
+ > .main > .main
+ > a
+ display block
+ margin-bottom 8px
+ text-align center
+
+ > div
+ cursor not-allowed !important
+
+ > *
+ pointer-events none
+
+ &:not([data-customize])
+ > .main > *:not(.main):empty
+ display none
+
+ > .customize
+ position fixed
+ z-index 1000
+ top 0
+ left 0
+ width 100%
+ height 48px
+ color var(--text)
+ background var(--desktopHeaderBg)
+ box-shadow 0 1px 1px rgba(#000, 0.075)
+
+ > a
+ display block
+ position absolute
+ z-index 1001
+ top 0
+ right 0
+ padding 0 16px
+ line-height 48px
+ text-decoration none
+ color var(--primaryForeground)
+ background var(--primary)
+ transition background 0.1s ease
+
+ &:hover
+ background var(--primaryLighten10)
+
+ &:active
+ background var(--primaryDarken10)
+ transition background 0s ease
+
+ > [data-icon]
+ margin-right 8px
+
+ > div
+ display flex
+ margin 0 auto
+ max-width 1220px - 32px
+
+ > div
+ width 50%
+
+ &.adder
+ > p
+ display inline
+ line-height 48px
+
+ &.trash
+ border-left solid 1px var(--faceDivider)
+
+ > div
+ width 100%
+ height 100%
+
+ > p
+ position absolute
+ top 0
+ left 0
+ width 100%
+ line-height 48px
+ margin 0
+ text-align center
+ pointer-events none
+
+ > .main
+ display flex
+ justify-content center
+ margin 0 auto
+ max-width 1240px
+
+ > *
+ .customize-container
+ cursor move
+ border-radius 6px
+
+ &:hover
+ box-shadow 0 0 8px rgba(64, 120, 200, 0.3)
+
+ > *
+ pointer-events none
+
+ > .main
+ padding 16px
+ width calc(100% - 280px * 2)
+ order 2
+
+ &.side
+ > .main
+ width calc(100% - 280px)
+ max-width 680px
+
+ > *:not(.main)
+ width 280px
+ padding 16px 0 16px 0
+
+ > *:not(:last-child)
+ margin-bottom 16px
+
+ > .left
+ padding-left 16px
+ order 1
+
+ > .right
+ padding-right 16px
+ order 3
+
+ &.side
+ @media (max-width 1000px)
+ > *:not(.main)
+ display none
+
+ > .main
+ width 100%
+ max-width 700px
+ margin 0 auto
+
+ &:not(.side)
+ @media (max-width 1200px)
+ > *:not(.main)
+ display none
+
+ > .main
+ width 100%
+ max-width 700px
+ margin 0 auto
+
+</style>
diff --git a/src/client/app/desktop/views/pages/note.vue b/src/client/app/desktop/views/home/note.vue
index 46d39d0b4a..90d3fd4357 100644
--- a/src/client/app/desktop/views/pages/note.vue
+++ b/src/client/app/desktop/views/home/note.vue
@@ -1,13 +1,11 @@
<template>
-<mk-ui>
- <main v-if="!fetching">
- <mk-note-detail :note="note"/>
- <footer>
- <router-link v-if="note.next" :to="note.next"><fa icon="angle-left"/> {{ $t('next') }}</router-link>
- <router-link v-if="note.prev" :to="note.prev">{{ $t('prev') }} <fa icon="angle-right"/></router-link>
- </footer>
- </main>
-</mk-ui>
+<div v-if="!fetching" class="kcthdwmv">
+ <mk-note-detail :note="note"/>
+ <footer>
+ <router-link v-if="note.next" :to="note.next"><fa icon="angle-left"/> {{ $t('next') }}</router-link>
+ <router-link v-if="note.prev" :to="note.prev">{{ $t('prev') }} <fa icon="angle-right"/></router-link>
+ </footer>
+</div>
</template>
<script lang="ts">
@@ -48,8 +46,7 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
-main
- padding 16px
+.kcthdwmv
text-align center
> footer
diff --git a/src/client/app/desktop/views/pages/tag.vue b/src/client/app/desktop/views/home/tag.vue
index 6e5db18af0..9e0978fb09 100644
--- a/src/client/app/desktop/views/pages/tag.vue
+++ b/src/client/app/desktop/views/home/tag.vue
@@ -1,11 +1,8 @@
<template>
-<mk-ui>
- <header :class="$style.header">
- <h1>#{{ $route.params.tag }}</h1>
- </header>
+<div>
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('no-posts-found', { q: $route.params.tag }) }}</p>
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/>
-</mk-ui>
+</div>
</template>
<script lang="ts">
@@ -96,17 +93,11 @@ export default Vue.extend({
</script>
<style lang="stylus" module>
-.header
- width 100%
- max-width 600px
- margin 0 auto
- color #555
-
.notes
- width 600px
- margin 0 auto
- border solid 1px rgba(#000, 0.075)
- border-radius 6px
+ background var(--face)
+ box-shadow var(--shadow)
+ border-radius var(--round)
+ overflow hidden
overflow hidden
.empty
diff --git a/src/client/app/desktop/views/components/timeline.core.vue b/src/client/app/desktop/views/home/timeline.core.vue
index 63bc20dc28..63bc20dc28 100644
--- a/src/client/app/desktop/views/components/timeline.core.vue
+++ b/src/client/app/desktop/views/home/timeline.core.vue
diff --git a/src/client/app/desktop/views/components/timeline.vue b/src/client/app/desktop/views/home/timeline.vue
index 0a91cfb59d..2f42b9723f 100644
--- a/src/client/app/desktop/views/components/timeline.vue
+++ b/src/client/app/desktop/views/home/timeline.vue
@@ -1,27 +1,30 @@
<template>
<div class="mk-timeline">
- <header>
- <span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
- <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
- <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
- <span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
- <span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span>
- <span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.title }}</span>
- <div class="buttons">
- <button :data-active="src == 'mentions'" @click="src = 'mentions'" :title="$t('mentions')"><fa icon="at"/><i class="badge" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></button>
- <button :data-active="src == 'messages'" @click="src = 'messages'" :title="$t('messages')"><fa :icon="['far', 'envelope']"/><i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></button>
- <button @click="chooseTag" :title="$t('hashtag')" ref="tagButton"><fa icon="hashtag"/></button>
- <button @click="chooseList" :title="$t('list')" ref="listButton"><fa icon="list"/></button>
- </div>
- </header>
- <x-core v-if="src == 'home'" ref="tl" key="home" src="home"/>
- <x-core v-if="src == 'local'" ref="tl" key="local" src="local"/>
- <x-core v-if="src == 'hybrid'" ref="tl" key="hybrid" src="hybrid"/>
- <x-core v-if="src == 'global'" ref="tl" key="global" src="global"/>
- <x-core v-if="src == 'mentions'" ref="tl" key="mentions" src="mentions"/>
- <x-core v-if="src == 'messages'" ref="tl" key="messages" src="messages"/>
- <x-core v-if="src == 'tag'" ref="tl" key="tag" src="tag" :tag-tl="tagTl"/>
- <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/>
+ <mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>
+ <div class="main">
+ <header>
+ <span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
+ <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
+ <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
+ <span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
+ <span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span>
+ <span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.title }}</span>
+ <div class="buttons">
+ <button :data-active="src == 'mentions'" @click="src = 'mentions'" :title="$t('mentions')"><fa icon="at"/><i class="badge" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></button>
+ <button :data-active="src == 'messages'" @click="src = 'messages'" :title="$t('messages')"><fa :icon="['far', 'envelope']"/><i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></button>
+ <button @click="chooseTag" :title="$t('hashtag')" ref="tagButton"><fa icon="hashtag"/></button>
+ <button @click="chooseList" :title="$t('list')" ref="listButton"><fa icon="list"/></button>
+ </div>
+ </header>
+ <x-core v-if="src == 'home'" ref="tl" key="home" src="home"/>
+ <x-core v-if="src == 'local'" ref="tl" key="local" src="local"/>
+ <x-core v-if="src == 'hybrid'" ref="tl" key="hybrid" src="hybrid"/>
+ <x-core v-if="src == 'global'" ref="tl" key="global" src="global"/>
+ <x-core v-if="src == 'mentions'" ref="tl" key="mentions" src="mentions"/>
+ <x-core v-if="src == 'messages'" ref="tl" key="messages" src="messages"/>
+ <x-core v-if="src == 'tag'" ref="tl" key="tag" src="tag" :tag-tl="tagTl"/>
+ <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/>
+ </div>
</div>
</template>
@@ -30,7 +33,7 @@ import Vue from 'vue';
import i18n from '../../../i18n';
import XCore from './timeline.core.vue';
import Menu from '../../../common/views/components/menu.vue';
-import MkSettingsWindow from './settings-window.vue';
+import MkSettingsWindow from '../components/settings-window.vue';
export default Vue.extend({
i18n: i18n('desktop/views/components/timeline.vue'),
@@ -184,81 +187,87 @@ export default Vue.extend({
<style lang="stylus" scoped>
.mk-timeline
- background var(--face)
- box-shadow var(--shadow)
- border-radius var(--round)
- overflow hidden
+ > .form
+ margin-bottom 16px
+ box-shadow var(--shadow)
+ border-radius var(--round)
- > header
- padding 0 8px
- z-index 10
- background var(--faceHeader)
- box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
+ > .main
+ background var(--face)
+ box-shadow var(--shadow)
+ border-radius var(--round)
+ overflow hidden
- > .buttons
- position absolute
- z-index 2
- top 0
- right 0
- padding-right 8px
+ > header
+ padding 0 8px
+ z-index 10
+ background var(--faceHeader)
+ box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
- > button
- padding 0 8px
- font-size 0.9em
- line-height 42px
- color var(--faceTextButton)
+ > .buttons
+ position absolute
+ z-index 2
+ top 0
+ right 0
+ padding-right 8px
+
+ > button
+ padding 0 8px
+ font-size 0.9em
+ line-height 42px
+ color var(--faceTextButton)
+
+ > .badge
+ position absolute
+ top -4px
+ right 4px
+ font-size 10px
+ color var(--notificationIndicator)
+
+ &:hover
+ color var(--faceTextButtonHover)
- > .badge
- position absolute
- top -4px
- right 4px
- font-size 10px
- color var(--notificationIndicator)
+ &[data-active]
+ color var(--primary)
+ cursor default
- &:hover
- color var(--faceTextButtonHover)
+ &:before
+ content ""
+ display block
+ position absolute
+ bottom 0
+ left 0
+ width 100%
+ height 2px
+ background var(--primary)
+
+ > span
+ display inline-block
+ padding 0 10px
+ line-height 42px
+ font-size 12px
+ user-select none
&[data-active]
color var(--primary)
cursor default
+ font-weight bold
&:before
content ""
display block
position absolute
bottom 0
- left 0
- width 100%
+ left -8px
+ width calc(100% + 16px)
height 2px
background var(--primary)
- > span
- display inline-block
- padding 0 10px
- line-height 42px
- font-size 12px
- user-select none
-
- &[data-active]
- color var(--primary)
- cursor default
- font-weight bold
-
- &:before
- content ""
- display block
- position absolute
- bottom 0
- left -8px
- width calc(100% + 16px)
- height 2px
- background var(--primary)
-
- &:not([data-active])
- color var(--desktopTimelineSrc)
- cursor pointer
+ &:not([data-active])
+ color var(--desktopTimelineSrc)
+ cursor pointer
- &:hover
- color var(--desktopTimelineSrcHover)
+ &:hover
+ color var(--desktopTimelineSrcHover)
</style>
diff --git a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue b/src/client/app/desktop/views/home/user/user.followers-you-know.vue
index 53949a7943..53949a7943 100644
--- a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue
+++ b/src/client/app/desktop/views/home/user/user.followers-you-know.vue
diff --git a/src/client/app/desktop/views/pages/user/user.friends.vue b/src/client/app/desktop/views/home/user/user.friends.vue
index e3182e91fa..e3182e91fa 100644
--- a/src/client/app/desktop/views/pages/user/user.friends.vue
+++ b/src/client/app/desktop/views/home/user/user.friends.vue
diff --git a/src/client/app/desktop/views/pages/user/user.header.vue b/src/client/app/desktop/views/home/user/user.header.vue
index 8352f662c0..a0d141fb97 100644
--- a/src/client/app/desktop/views/pages/user/user.header.vue
+++ b/src/client/app/desktop/views/home/user/user.header.vue
@@ -15,6 +15,13 @@
</div>
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
<div class="body">
+ <div class="actions" v-if="$store.getters.isSignedIn">
+ <template v-if="$store.state.i.id != user.id">
+ <p class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</p>
+ <mk-follow-button :user="user" :inline="true" class="follow"/>
+ </template>
+ <ui-button @click="menu" ref="menu" :inline="true"><fa icon="ellipsis-h"/></ui-button>
+ </div>
<div class="description">
<mfm v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
</div>
@@ -45,6 +52,7 @@
import Vue from 'vue';
import i18n from '../../../../i18n';
import * as age from 's-age';
+import XUserMenu from '../../../../common/views/components/user-menu.vue';
export default Vue.extend({
i18n: i18n('desktop/views/pages/user/user.header.vue'),
@@ -99,6 +107,13 @@ export default Vue.extend({
this.$updateBanner().then(i => {
this.user.bannerUrl = i.bannerUrl;
});
+ },
+
+ menu() {
+ this.$root.new(XUserMenu, {
+ source: this.$refs.menu.$el,
+ user: this.user
+ });
}
}
});
@@ -187,6 +202,10 @@ export default Vue.extend({
padding 16px 16px 16px 154px
color var(--text)
+ > .actions
+ > .follow
+ width 200px
+
> .fields
margin-top 16px
diff --git a/src/client/app/desktop/views/pages/user/user.integrations.integration.vue b/src/client/app/desktop/views/home/user/user.integrations.integration.vue
index 4791226881..4791226881 100644
--- a/src/client/app/desktop/views/pages/user/user.integrations.integration.vue
+++ b/src/client/app/desktop/views/home/user/user.integrations.integration.vue
diff --git a/src/client/app/desktop/views/pages/user/user.integrations.vue b/src/client/app/desktop/views/home/user/user.integrations.vue
index d796ff9321..d796ff9321 100644
--- a/src/client/app/desktop/views/pages/user/user.integrations.vue
+++ b/src/client/app/desktop/views/home/user/user.integrations.vue
diff --git a/src/client/app/desktop/views/pages/user/user.photos.vue b/src/client/app/desktop/views/home/user/user.photos.vue
index 13645b9314..005961aaa3 100644
--- a/src/client/app/desktop/views/pages/user/user.photos.vue
+++ b/src/client/app/desktop/views/home/user/user.photos.vue
@@ -87,7 +87,7 @@ export default Vue.extend({
> .img
flex 1 1 33%
width 33%
- height 80px
+ height 120px
background-position center center
background-size cover
background-clip content-box
diff --git a/src/client/app/desktop/views/pages/user/user.timeline.vue b/src/client/app/desktop/views/home/user/user.timeline.vue
index 0571ce76f1..0571ce76f1 100644
--- a/src/client/app/desktop/views/pages/user/user.timeline.vue
+++ b/src/client/app/desktop/views/home/user/user.timeline.vue
diff --git a/src/client/app/desktop/views/home/user/user.vue b/src/client/app/desktop/views/home/user/user.vue
new file mode 100644
index 0000000000..32b1dc2e45
--- /dev/null
+++ b/src/client/app/desktop/views/home/user/user.vue
@@ -0,0 +1,109 @@
+<template>
+<div class="xygkxeaeontfaokvqmiblezmhvhostak" v-if="!fetching">
+ <div class="is-suspended" v-if="user.isSuspended"><fa icon="exclamation-triangle"/> {{ $t('@.user-suspended') }}</div>
+ <div class="is-remote" v-if="user.host != null"><fa icon="exclamation-triangle"/> {{ $t('@.is-remote-user') }}<a :href="user.url || user.uri" target="_blank">{{ $t('@.view-on-remote') }}</a></div>
+ <div class="main">
+ <x-header :user="user"/>
+ <mk-note-detail v-for="n in user.pinnedNotes" :key="n.id" :note="n" :compact="true"/>
+ <x-integrations :user="user"/>
+ <!--<mk-calendar @chosen="warp" :start="new Date(user.createdAt)"/>-->
+ <div class="activity">
+ <mk-widget-container :show-header="true" :naked="false">
+ <template slot="header"><fa icon="chart-bar"/>{{ $t('activity') }}</template>
+ <x-activity :user="user" :limit="35" style="padding: 16px;"/>
+ </mk-widget-container>
+ </div>
+ <x-photos :user="user"/>
+ <x-friends :user="user"/>
+ <x-followers-you-know v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
+ <x-timeline class="timeline" ref="tl" :user="user"/>
+ </div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../../../i18n';
+import parseAcct from '../../../../../../misc/acct/parse';
+import Progress from '../../../../common/scripts/loading';
+import XHeader from './user.header.vue';
+import XTimeline from './user.timeline.vue';
+import XPhotos from './user.photos.vue';
+import XFollowersYouKnow from './user.followers-you-know.vue';
+import XFriends from './user.friends.vue';
+import XIntegrations from './user.integrations.vue';
+import XActivity from '../../../../common/views/components/activity.vue';
+
+export default Vue.extend({
+ i18n: i18n(),
+ components: {
+ XHeader,
+ XTimeline,
+ XPhotos,
+ XFollowersYouKnow,
+ XFriends,
+ XIntegrations,
+ XActivity
+ },
+ data() {
+ return {
+ fetching: true,
+ user: null
+ };
+ },
+ watch: {
+ $route: 'fetch'
+ },
+ created() {
+ this.fetch();
+ },
+ methods: {
+ fetch() {
+ this.fetching = true;
+ Progress.start();
+ this.$root.api('users/show', parseAcct(this.$route.params.user)).then(user => {
+ this.user = user;
+ this.fetching = false;
+ Progress.done();
+ });
+ },
+
+ warp(date) {
+ (this.$refs.tl as any).warp(date);
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.xygkxeaeontfaokvqmiblezmhvhostak
+ width 100%
+ margin 0 auto
+
+ > .is-suspended
+ > .is-remote
+ margin-bottom 16px
+ padding 14px 16px
+ font-size 14px
+ box-shadow var(--shadow)
+ border-radius var(--round)
+
+ &.is-suspended
+ color var(--suspendedInfoFg)
+ background var(--suspendedInfoBg)
+
+ &.is-remote
+ color var(--remoteInfoFg)
+ background var(--remoteInfoBg)
+
+ > a
+ font-weight bold
+
+ > .main
+ > *
+ margin-bottom 16px
+
+ > .timeline
+ box-shadow var(--shadow)
+
+</style>
diff --git a/src/client/app/desktop/views/pages/deck/deck.hashtag-column.vue b/src/client/app/desktop/views/pages/deck/deck.hashtag-column.vue
deleted file mode 100644
index b2a6cd5837..0000000000
--- a/src/client/app/desktop/views/pages/deck/deck.hashtag-column.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-<template>
-<x-column>
- <span slot="header">
- <fa icon="hashtag"/><span>{{ tag }}</span>
- </span>
-
- <div class="xroyrflcmhhtmlwmyiwpfqiirqokfueb">
- <div ref="chart" class="chart"></div>
- <x-hashtag-tl :tag-tl="tagTl" class="tl"/>
- </div>
-</x-column>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import XColumn from './deck.column.vue';
-import XHashtagTl from './deck.hashtag-tl.vue';
-import ApexCharts from 'apexcharts';
-
-export default Vue.extend({
- components: {
- XColumn,
- XHashtagTl
- },
-
- props: {
- tag: {
- type: String,
- required: true
- }
- },
-
- computed: {
- tagTl(): any {
- return {
- query: [[this.tag]]
- };
- }
- },
-
- mounted() {
- this.$root.api('charts/hashtag', {
- tag: this.tag,
- span: 'hour',
- limit: 24
- }).then(stats => {
- const local = [];
- const remote = [];
-
- const now = new Date();
- const y = now.getFullYear();
- const m = now.getMonth();
- const d = now.getDate();
- const h = now.getHours();
-
- for (let i = 0; i < 24; i++) {
- const x = new Date(y, m, d, h - i);
- local.push([x, stats.local.count[i]]);
- remote.push([x, stats.remote.count[i]]);
- }
-
- const chart = new ApexCharts(this.$refs.chart, {
- chart: {
- type: 'area',
- height: 70,
- sparkline: {
- enabled: true
- },
- },
- grid: {
- clipMarkers: false,
- padding: {
- top: 16,
- right: 16,
- bottom: 16,
- left: 16
- }
- },
- stroke: {
- curve: 'straight',
- width: 2
- },
- series: [{
- name: 'Local',
- data: local
- }, {
- name: 'Remote',
- data: remote
- }],
- xaxis: {
- type: 'datetime',
- }
- });
-
- chart.render();
- });
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.xroyrflcmhhtmlwmyiwpfqiirqokfueb
- background var(--deckColumnBg)
-
- > .chart
- margin-bottom 16px
- background var(--face)
-
- > .tl
- background var(--face)
-
-</style>
diff --git a/src/client/app/desktop/views/pages/home-customize.vue b/src/client/app/desktop/views/pages/home-customize.vue
deleted file mode 100644
index e0460abcd0..0000000000
--- a/src/client/app/desktop/views/pages/home-customize.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
-<mk-home customize/>
-</template>
diff --git a/src/client/app/desktop/views/pages/home.vue b/src/client/app/desktop/views/pages/home.vue
deleted file mode 100644
index 19e00880af..0000000000
--- a/src/client/app/desktop/views/pages/home.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-<template>
-<mk-ui>
- <mk-home :mode="mode" @loaded="loaded" ref="home" v-hotkey.global="keymap"/>
-</mk-ui>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import Progress from '../../../common/scripts/loading';
-
-export default Vue.extend({
- props: {
- mode: {
- type: String,
- default: 'timeline'
- }
- },
- computed: {
- keymap(): any {
- return {
- 't': this.focus
- };
- }
- },
- mounted() {
- document.title = this.$root.instanceName;
-
- Progress.start();
- },
- methods: {
- loaded() {
- Progress.done();
- },
- focus() {
- this.$refs.home.focus();
- }
- }
-});
-</script>
diff --git a/src/client/app/desktop/views/pages/index.vue b/src/client/app/desktop/views/pages/index.vue
deleted file mode 100644
index c531e00e4f..0000000000
--- a/src/client/app/desktop/views/pages/index.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-<template>
-<component :is="page"></component>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import Home from './home.vue';
-import Welcome from './welcome.vue';
-import Deck from './deck/deck.vue';
-
-export default Vue.extend({
- components: {
- Home,
- Deck,
- Welcome
- },
-
- computed: {
- page(): string {
- if (!this.$store.getters.isSignedIn) return 'welcome';
- return this.$store.state.device.deckDefault ? 'deck' : 'home';
- }
- }
-});
-</script>
diff --git a/src/client/app/desktop/views/pages/user/user.profile.vue b/src/client/app/desktop/views/pages/user/user.profile.vue
deleted file mode 100644
index 026f84dc8a..0000000000
--- a/src/client/app/desktop/views/pages/user/user.profile.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<template>
-<div class="profile" v-if="$store.getters.isSignedIn">
- <div class="friend-form" v-if="$store.state.i.id != user.id">
- <mk-follow-button :user="user" block/>
- <p class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</p>
- </div>
- <div class="action-form">
- <ui-button @click="menu" ref="menu">{{ $t('menu') }}</ui-button>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import i18n from '../../../../i18n';
-import XUserMenu from '../../../../common/views/components/user-menu.vue';
-
-export default Vue.extend({
- i18n: i18n('desktop/views/pages/user/user.profile.vue'),
- props: ['user'],
-
- methods: {
- menu() {
- this.$root.new(XUserMenu, {
- source: this.$refs.menu.$el,
- user: this.user
- });
- },
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.profile
- background var(--face)
- box-shadow var(--shadow)
- border-radius var(--round)
-
- > *:first-child
- border-top none !important
-
- > .friend-form
- padding 16px
- text-align center
- border-bottom solid 1px var(--faceDivider)
-
- > .followed
- margin 12px 0 0 0
- padding 0
- text-align center
- line-height 24px
- font-size 0.8em
- color var(--text)
- border-radius 4px
-
- > .action-form
- padding 16px
- text-align center
-
- > *
- width 100%
-
- &:not(:last-child)
- margin-bottom 12px
-
-</style>
diff --git a/src/client/app/desktop/views/pages/user/user.vue b/src/client/app/desktop/views/pages/user/user.vue
deleted file mode 100644
index 19f646927b..0000000000
--- a/src/client/app/desktop/views/pages/user/user.vue
+++ /dev/null
@@ -1,155 +0,0 @@
-<template>
-<mk-ui>
- <div class="xygkxeaeontfaokvqmiblezmhvhostak" v-if="!fetching">
- <div class="is-suspended" v-if="user.isSuspended"><fa icon="exclamation-triangle"/> {{ $t('@.user-suspended') }}</div>
- <div class="is-remote" v-if="user.host != null"><fa icon="exclamation-triangle"/> {{ $t('@.is-remote-user') }}<a :href="user.url || user.uri" target="_blank">{{ $t('@.view-on-remote') }}</a></div>
- <main>
- <div class="main">
- <x-header :user="user"/>
- <mk-note-detail v-for="n in user.pinnedNotes" :key="n.id" :note="n" :compact="true"/>
- <x-timeline class="timeline" ref="tl" :user="user"/>
- </div>
- <div class="side">
- <div class="instance" v-if="!$store.getters.isSignedIn"><mk-instance/></div>
- <x-profile :user="user"/>
- <x-integrations :user="user"/>
- <mk-calendar @chosen="warp" :start="new Date(user.createdAt)"/>
- <mk-activity :user="user"/>
- <x-photos :user="user"/>
- <x-friends :user="user"/>
- <x-followers-you-know v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
- <div class="nav"><mk-nav/></div>
- </div>
- </main>
- </div>
-</mk-ui>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import i18n from '../../../../i18n';
-import parseAcct from '../../../../../../misc/acct/parse';
-import Progress from '../../../../common/scripts/loading';
-import XHeader from './user.header.vue';
-import XTimeline from './user.timeline.vue';
-import XProfile from './user.profile.vue';
-import XPhotos from './user.photos.vue';
-import XFollowersYouKnow from './user.followers-you-know.vue';
-import XFriends from './user.friends.vue';
-import XIntegrations from './user.integrations.vue';
-
-export default Vue.extend({
- i18n: i18n(),
- components: {
- XHeader,
- XTimeline,
- XProfile,
- XPhotos,
- XFollowersYouKnow,
- XFriends,
- XIntegrations
- },
- data() {
- return {
- fetching: true,
- user: null
- };
- },
- watch: {
- $route: 'fetch'
- },
- created() {
- this.fetch();
- },
- methods: {
- fetch() {
- this.fetching = true;
- Progress.start();
- this.$root.api('users/show', parseAcct(this.$route.params.user)).then(user => {
- this.user = user;
- this.fetching = false;
- Progress.done();
- });
- },
-
- warp(date) {
- (this.$refs.tl as any).warp(date);
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.xygkxeaeontfaokvqmiblezmhvhostak
- max-width 980px
- min-width 720px
- padding 16px
- margin 0 auto
-
- > .is-suspended
- > .is-remote
- margin-bottom 16px
- padding 14px 16px
- font-size 14px
- box-shadow var(--shadow)
- border-radius var(--round)
-
- &.is-suspended
- color var(--suspendedInfoFg)
- background var(--suspendedInfoBg)
-
- &.is-remote
- color var(--remoteInfoFg)
- background var(--remoteInfoBg)
-
- > a
- font-weight bold
-
- > main
- display flex
- justify-content center
-
- > .main
- > .side
- > *:not(:last-child)
- margin-bottom 16px
-
- > .main
- flex 1
- min-width 0 // SEE: http://kudakurage.hatenadiary.com/entry/2016/04/01/232722
- margin-right 16px
-
- > .timeline
- box-shadow var(--shadow)
-
- > .side
- width 275px
- flex-shrink 0
-
- > p
- display block
- margin 0
- padding 0 12px
- text-align center
- font-size 0.8em
- color var(--text)
-
- > .instance
- box-shadow var(--shadow)
- border-radius var(--round)
-
- > .nav
- padding 16px
- font-size 12px
- color var(--text)
- background var(--face)
- box-shadow var(--shadow)
- border-radius var(--round)
-
- a
- color var(--text)99
-
- i
- color var(--text)
-
-</style>
diff --git a/src/client/app/desktop/views/widgets/customize.vue b/src/client/app/desktop/views/widgets/customize.vue
new file mode 100644
index 0000000000..eb71910382
--- /dev/null
+++ b/src/client/app/desktop/views/widgets/customize.vue
@@ -0,0 +1,21 @@
+<template>
+<div class="mkw-customize">
+ <ui-button @click="customize()">{{ $t('@.customize-home') }}</ui-button>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../common/define-widget';
+import i18n from '../../../i18n';
+
+export default define({
+ name: 'customize',
+}).extend({
+ i18n: i18n(),
+ methods: {
+ customize(date) {
+ location.href = '/?customize';
+ }
+ }
+});
+</script>
diff --git a/src/client/app/desktop/views/widgets/index.ts b/src/client/app/desktop/views/widgets/index.ts
index 7c074080c1..38a661671f 100644
--- a/src/client/app/desktop/views/widgets/index.ts
+++ b/src/client/app/desktop/views/widgets/index.ts
@@ -9,6 +9,7 @@ import wPolls from './polls.vue';
import wPostForm from './post-form.vue';
import wMessaging from './messaging.vue';
import wProfile from './profile.vue';
+import wCustomize from './customize.vue';
Vue.component('mkw-notifications', wNotifications);
Vue.component('mkw-timemachine', wTimemachine);
@@ -19,3 +20,4 @@ Vue.component('mkw-polls', wPolls);
Vue.component('mkw-post-form', wPostForm);
Vue.component('mkw-messaging', wMessaging);
Vue.component('mkw-profile', wProfile);
+Vue.component('mkw-customize', wCustomize);
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index 2f18030f0d..710bef8b65 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -350,7 +350,7 @@ if (localStorage.getItem('should-refresh') == 'true') {
}
// MiOSを初期化してコールバックする
-export default (callback: (launch: (router: VueRouter) => [Vue, MiOS]) => void, sw = false) => {
+export default (callback: (launch: (router: VueRouter) => [Vue, MiOS], os: MiOS) => void, sw = false) => {
const os = new MiOS(sw);
os.init(() => {
@@ -436,11 +436,6 @@ export default (callback: (launch: (router: VueRouter) => [Vue, MiOS]) => void,
});
//#endregion
- // Navigation hook
- router.beforeEach((to, from, next) => {
- next(os.store.state.navHook && os.store.state.navHook(to) ? false : undefined);
- });
-
document.addEventListener('visibilitychange', () => {
if (!document.hidden) {
os.store.commit('clearBehindNotes');
@@ -507,6 +502,6 @@ export default (callback: (launch: (router: VueRouter) => [Vue, MiOS]) => void,
return [app, os] as [Vue, MiOS];
};
- callback(launch);
+ callback(launch, os);
});
};
diff --git a/src/client/app/mobile/views/pages/user/home.vue b/src/client/app/mobile/views/pages/user/home.vue
index 09b4c3f265..98b4f44476 100644
--- a/src/client/app/mobile/views/pages/user/home.vue
+++ b/src/client/app/mobile/views/pages/user/home.vue
@@ -49,7 +49,7 @@ export default Vue.extend({
XPhotos,
XFriends,
XFollowersYouKnow,
- XActivity: () => import('../../components/activity.vue').then(m => m.default)
+ XActivity: () => import('../../../../common/views/components/activity.vue').then(m => m.default)
},
props: ['user']
});
diff --git a/src/client/app/mobile/views/widgets/activity.vue b/src/client/app/mobile/views/widgets/activity.vue
index 4dcab8e3b5..08526416cd 100644
--- a/src/client/app/mobile/views/widgets/activity.vue
+++ b/src/client/app/mobile/views/widgets/activity.vue
@@ -21,7 +21,7 @@ export default define({
}).extend({
i18n: i18n(),
components: {
- XActivity: () => import('../components/activity.vue').then(m => m.default)
+ XActivity: () => import('../../../common/views/components/activity.vue').then(m => m.default)
},
methods: {
func() {
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index d0f61f8bc1..a91164c0b5 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -10,7 +10,6 @@ const defaultSettings = {
home: null,
mobileHome: [],
deck: null,
- deckNav: true,
keepCw: false,
tagTimelines: [],
fetchOnScroll: true,
@@ -67,8 +66,7 @@ const defaultDeviceSettings = {
deckColumnAlign: 'center',
deckColumnWidth: 'normal',
mobileNotificationPosition: 'bottom',
- deckTemporaryColumn: null,
- deckDefault: false,
+ deckMode: false,
useOsDefaultEmojis: false,
disableShowingAnimatedImages: false
};
@@ -82,7 +80,6 @@ export default (os: MiOS) => new Vuex.Store({
i: null,
indicate: false,
uiHeaderHeight: 0,
- navHook: null,
behindNotes: []
},
@@ -107,10 +104,6 @@ export default (os: MiOS) => new Vuex.Store({
state.uiHeaderHeight = height;
},
- navHook(state, callback) {
- state.navHook = callback;
- },
-
pushBehindNote(state, note) {
if (note.userId === state.i.id) return;
if (state.behindNotes.some(n => n.id === note.id)) return;