From fb8ed718cec074bb021bf7d594bbd42dba558ef0 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sat, 10 Apr 2021 13:38:24 +0900
Subject: [PATCH] Improve UI

---
 src/client/components/timeline.vue |  8 ++++++-
 src/client/pages/note.vue          |  6 +++++
 src/client/pages/notifications.vue | 11 +++++++--
 src/client/pages/timeline.vue      | 11 +++++----
 src/client/pages/user/index.vue    |  4 ----
 src/client/ui/_common_/header.vue  | 38 +++++++++++++++++++++++-------
 6 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/src/client/components/timeline.vue b/src/client/components/timeline.vue
index c2ab0b005d..faa3984638 100644
--- a/src/client/components/timeline.vue
+++ b/src/client/components/timeline.vue
@@ -56,6 +56,7 @@ export default defineComponent({
 				includeLocalRenotes: this.$store.state.showLocalRenotes
 			},
 			query: {},
+			date: null
 		};
 	},
 
@@ -157,7 +158,7 @@ export default defineComponent({
 			endpoint: endpoint,
 			limit: 10,
 			params: init => ({
-				untilDate: init ? undefined : (this.date ? this.date.getTime() : undefined),
+				untilDate: this.date?.getTime(),
 				...this.baseQuery, ...this.query
 			})
 		};
@@ -171,6 +172,11 @@ export default defineComponent({
 	methods: {
 		focus() {
 			this.$refs.tl.focus();
+		},
+
+		timetravel(date?: Date) {
+			this.date = date;
+			this.$refs.tl.reload();
 		}
 	}
 });
diff --git a/src/client/pages/note.vue b/src/client/pages/note.vue
index 921e73c0bc..90cb98c40e 100644
--- a/src/client/pages/note.vue
+++ b/src/client/pages/note.vue
@@ -45,6 +45,7 @@ import MkRemoteCaution from '@client/components/remote-caution.vue';
 import MkButton from '@client/components/ui/button.vue';
 import * as os from '@client/os';
 import * as symbols from '@client/symbols';
+import { url } from '@client/config';
 
 export default defineComponent({
 	components: {
@@ -65,6 +66,11 @@ export default defineComponent({
 			[symbols.PAGE_INFO]: computed(() => this.note ? {
 				title: this.$ts.note,
 				avatar: this.note.user,
+				share: {
+					title: this.$t('noteOf', { user: this.note.user.name }),
+					text: this.note.text,
+					url: `${url}/notes/${this.note.id}`
+				},
 			} : null),
 			note: null,
 			clips: null,
diff --git a/src/client/pages/notifications.vue b/src/client/pages/notifications.vue
index 6f38d7739f..25605988ed 100644
--- a/src/client/pages/notifications.vue
+++ b/src/client/pages/notifications.vue
@@ -6,7 +6,7 @@
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import { faBell } from '@fortawesome/free-solid-svg-icons';
+import { faBell, faCheck } from '@fortawesome/free-solid-svg-icons';
 import Progress from '@client/scripts/loading';
 import XNotifications from '@client/components/notifications.vue';
 import * as os from '@client/os';
@@ -21,7 +21,14 @@ export default defineComponent({
 		return {
 			[symbols.PAGE_INFO]: {
 				title: this.$ts.notifications,
-				icon: faBell
+				icon: faBell,
+				actions: [{
+					text: this.$ts.markAllAsRead,
+					icon: faCheck,
+					handler: () => {
+						os.apiWithDialog('notifications/mark-all-as-read');
+					}
+				}]
 			},
 		};
 	},
diff --git a/src/client/pages/timeline.vue b/src/client/pages/timeline.vue
index da81627122..947efad2b7 100644
--- a/src/client/pages/timeline.vue
+++ b/src/client/pages/timeline.vue
@@ -38,7 +38,7 @@
 <script lang="ts">
 import { defineComponent, defineAsyncComponent, computed } from 'vue';
 import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite, faSatelliteDish, faCircle, faEllipsisH, faPencilAlt, faAt } from '@fortawesome/free-solid-svg-icons';
-import { faComments, faEnvelope } from '@fortawesome/free-regular-svg-icons';
+import { faComments, faEnvelope, faCalendarAlt } from '@fortawesome/free-regular-svg-icons';
 import Progress from '@client/scripts/loading';
 import XTimeline from '@client/components/timeline.vue';
 import XPostForm from '@client/components/post-form.vue';
@@ -67,10 +67,11 @@ export default defineComponent({
 			[symbols.PAGE_INFO]: computed(() => ({
 				title: this.$ts.timeline,
 				icon: this.src === 'local' ? faComments : this.src === 'social' ? faShareAlt : this.src === 'global' ? faGlobe : faHome,
-				action: {
-					icon: faPencilAlt,
-					handler: () => os.post()
-				}
+				actions: [{
+					icon: faCalendarAlt,
+					text: this.$ts.jumpToSpecifiedDate,
+					handler: this.timetravel
+				}]
 			})),
 			faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faSatelliteDish, faCircle, faEllipsisH, faAt, faEnvelope,
 		};
diff --git a/src/client/pages/user/index.vue b/src/client/pages/user/index.vue
index 1adf57f600..6351014956 100644
--- a/src/client/pages/user/index.vue
+++ b/src/client/pages/user/index.vue
@@ -276,10 +276,6 @@ export default defineComponent({
 					title: this.user.name,
 					url: `${url}/@${this.user.username}`
 				},
-				action: {
-					icon: faEllipsisH,
-					handler: this.menu
-				}
 			} : null),
 			user: null,
 			error: null,
diff --git a/src/client/ui/_common_/header.vue b/src/client/ui/_common_/header.vue
index 4c914edbbd..f95447096f 100644
--- a/src/client/ui/_common_/header.vue
+++ b/src/client/ui/_common_/header.vue
@@ -12,8 +12,12 @@
 				<MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/>
 			</div>
 		</div>
-		<button class="_button menu" @click.stop="menu"><Fa :icon="faEllipsisH"/></button>
-		<!--<button class="_button action" v-if="info.action" @click.stop="info.action.handler"><Fa :icon="info.action.icon" :key="info.action.icon"/></button>-->
+		<div class="buttons">
+			<template v-if="info.actions && showActions">
+				<button v-for="action in info.actions" class="_button button" @click.stop="action.handler" v-tooltip="action.text"><Fa :icon="action.icon"/></button>
+			</template>
+			<button v-if="showMenu" class="_button button" @click.stop="menu"><Fa :icon="faEllipsisH"/></button>
+		</div>
 	</template>
 </div>
 </template>
@@ -43,11 +47,21 @@ export default defineComponent({
 	data() {
 		return {
 			canBack: false,
+			showActions: false,
 			height: 0,
 			faChevronLeft, faCircle, faShareAlt, faEllipsisH,
 		};
 	},
 
+	computed: {
+		showMenu() {
+			if (this.info.actions != null && !this.showActions) return true;
+			if (this.info.menu != null) return true;
+			if (this.info.share != null) return true;
+			return false;
+		}
+	},
+
 	watch: {
 		$route: {
 			handler(to, from) {
@@ -59,8 +73,10 @@ export default defineComponent({
 
 	mounted() {
 		this.height = this.$el.parentElement.offsetHeight + 'px';
+		this.showActions = this.$el.parentElement.offsetWidth >= 500;
 		new ResizeObserver((entries, observer) => {
 			this.height = this.$el.parentElement.offsetHeight + 'px';
+			this.showActions = this.$el.parentElement.offsetWidth >= 500;
 		}).observe(this.$el);
 	},
 
@@ -99,21 +115,25 @@ export default defineComponent({
 		}
 	}
 
-	> .back,
-	> .menu {
+	> .back {
 		position: absolute;
 		z-index: 1;
 		top: 0;
+		left: 0;
 		height: var(--height);
 		width: var(--height);
 	}
 
-	> .back {
-		left: 0;
-	}
-
-	> .menu {
+	> .buttons {
+		position: absolute;
+		z-index: 1;
+		top: 0;
 		right: 0;
+
+		> .button {
+			height: var(--height);
+			width: var(--height);
+		}
 	}
 
 	> .titleContainer {