summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2019-04-18 19:40:23 +0900
committersyuilo <syuilotan@yahoo.co.jp>2019-04-18 19:40:23 +0900
commit7827aeb6951bfd0dae1799601dff3f207a3d2363 (patch)
treefa81558061c2743bc5d6566d916f7df4a3dad34e /src
parentFix API definition (diff)
downloadsharkey-7827aeb6951bfd0dae1799601dff3f207a3d2363.tar.gz
sharkey-7827aeb6951bfd0dae1799601dff3f207a3d2363.tar.bz2
sharkey-7827aeb6951bfd0dae1799601dff3f207a3d2363.zip
Resolve #4735
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/scripts/search.ts64
-rw-r--r--src/client/app/common/views/components/dialog.vue50
-rw-r--r--src/client/app/desktop/views/components/ui.header.search.vue27
-rw-r--r--src/client/app/desktop/views/home/timeline.core.vue15
-rw-r--r--src/client/app/init.ts6
-rw-r--r--src/client/app/mobile/views/components/ui.nav.vue26
-rw-r--r--src/client/app/mobile/views/pages/home.timeline.vue10
7 files changed, 127 insertions, 71 deletions
diff --git a/src/client/app/common/scripts/search.ts b/src/client/app/common/scripts/search.ts
new file mode 100644
index 0000000000..c44581817b
--- /dev/null
+++ b/src/client/app/common/scripts/search.ts
@@ -0,0 +1,64 @@
+import { faHistory } from '@fortawesome/free-solid-svg-icons';
+
+export async function search(v: any, q: string) {
+ q = q.trim();
+
+ if (q.startsWith('@')) {
+ v.$router.push(`/${q}`);
+ return;
+ }
+
+ if (q.startsWith('#')) {
+ v.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
+ return;
+ }
+
+ // like 2018/03/12
+ if (/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}/.test(q.replace(/-/g, '/'))) {
+ const date = new Date(q.replace(/-/g, '/'));
+
+ // 日付しか指定されてない場合、例えば 2018/03/12 ならユーザーは
+ // 2018/03/12 のコンテンツを「含む」結果になることを期待するはずなので
+ // 23時間59分進める(そのままだと 2018/03/12 00:00:00 「まで」の
+ // 結果になってしまい、2018/03/12 のコンテンツは含まれない)
+ if (q.replace(/-/g, '/').match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/)) {
+ date.setHours(23, 59, 59, 999);
+ }
+
+ v.$root.$emit('warp', date);
+ v.$root.dialog({
+ icon: faHistory,
+ splash: true,
+ });
+ return;
+ }
+
+ if (q.startsWith('https://')) {
+ const dialog = v.$root.dialog({
+ type: 'waiting',
+ text: v.$t('@.fetching-as-ap-object'),
+ showOkButton: false,
+ showCancelButton: false,
+ cancelableByBgClick: false
+ });
+
+ try {
+ const res = await v.$root.api('ap/show', {
+ uri: q
+ });
+ dialog.close();
+ if (res.type == 'User') {
+ v.$router.push(`/@${res.object.username}@${res.object.host}`);
+ } else if (res.type == 'Note') {
+ v.$router.push(`/notes/${res.object.id}`);
+ }
+ } catch (e) {
+ dialog.close();
+ // TODO: Show error
+ }
+
+ return;
+ }
+
+ v.$router.push(`/search?q=${encodeURIComponent(q)}`);
+}
diff --git a/src/client/app/common/views/components/dialog.vue b/src/client/app/common/views/components/dialog.vue
index 771b1237ee..c1ee7958c0 100644
--- a/src/client/app/common/views/components/dialog.vue
+++ b/src/client/app/common/views/components/dialog.vue
@@ -6,7 +6,17 @@
<mk-signin/>
</template>
<template v-else>
- <div class="icon" v-if="!input && !select && !user" :class="type"><fa :icon="icon"/></div>
+ <div class="icon" v-if="icon">
+ <fa :icon="icon"/>
+ </div>
+ <div class="icon" v-else-if="!input && !select && !user" :class="type">
+ <fa icon="check" v-if="type === 'success'"/>
+ <fa :icon="faTimesCircle" v-if="type === 'error'"/>
+ <fa icon="exclamation-triangle" v-if="type === 'warning'"/>
+ <fa icon="info-circle" v-if="type === 'info'"/>
+ <fa :icon="faQuestionCircle" v-if="type === 'question'"/>
+ <fa icon="spinner" pulse v-if="type === 'waiting'"/>
+ </div>
<header v-if="title" v-html="title"></header>
<div class="body" v-if="text" v-html="text"></div>
<ui-input v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></ui-input>
@@ -14,8 +24,8 @@
<ui-select v-if="select" v-model="selectedValue" autofocus>
<option v-for="item in select.items" :value="item.value">{{ item.text }}</option>
</ui-select>
- <ui-horizon-group no-grow class="buttons fit-bottom" v-if="!splash">
- <ui-button @click="ok" primary :autofocus="!input && !select && !user">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
+ <ui-horizon-group no-grow class="buttons fit-bottom" v-if="!splash && (showOkButton || showCancelButton)">
+ <ui-button @click="ok" v-if="showOkButton" primary :autofocus="!input && !select && !user">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
<ui-button @click="cancel" v-if="showCancelButton || input || select || user">{{ $t('@.cancel') }}</ui-button>
</ui-horizon-group>
</template>
@@ -55,10 +65,21 @@ export default Vue.extend({
user: {
required: false
},
+ icon: {
+ required: false
+ },
+ showOkButton: {
+ type: Boolean,
+ default: true
+ },
showCancelButton: {
type: Boolean,
default: false
},
+ cancelableByBgClick: {
+ type: Boolean,
+ default: true
+ },
splash: {
type: Boolean,
default: false
@@ -69,22 +90,11 @@ export default Vue.extend({
return {
inputValue: this.input && this.input.default ? this.input.default : null,
userInputValue: null,
- selectedValue: null
+ selectedValue: null,
+ faTimesCircle, faQuestionCircle
};
},
- computed: {
- icon(): any {
- switch (this.type) {
- case 'success': return 'check';
- case 'error': return faTimesCircle;
- case 'warning': return 'exclamation-triangle';
- case 'info': return 'info-circle';
- case 'question': return faQuestionCircle;
- }
- }
- },
-
mounted() {
this.$nextTick(() => {
(this.$refs.bg as any).style.pointerEvents = 'auto';
@@ -113,6 +123,8 @@ export default Vue.extend({
methods: {
async ok() {
+ if (!this.showOkButton) return;
+
if (this.user) {
const user = await this.$root.api('users/show', parseAcct(this.userInputValue));
if (user) {
@@ -156,7 +168,9 @@ export default Vue.extend({
},
onBgClick() {
- this.cancel();
+ if (this.cancelableByBgClick) {
+ this.cancel();
+ }
},
onInputKeydown(e) {
@@ -240,7 +254,7 @@ export default Vue.extend({
margin-top 8px
> .body
- margin 16px 0
+ margin 16px 0 0 0
> .buttons
margin-top 16px
diff --git a/src/client/app/desktop/views/components/ui.header.search.vue b/src/client/app/desktop/views/components/ui.header.search.vue
index 4ade74bc64..0cf5ca6f32 100644
--- a/src/client/app/desktop/views/components/ui.header.search.vue
+++ b/src/client/app/desktop/views/components/ui.header.search.vue
@@ -9,6 +9,7 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../i18n';
+import { search } from '../../../common/scripts/search';
export default Vue.extend({
i18n: i18n('desktop/views/components/ui.header.search.vue'),
@@ -22,29 +23,11 @@ export default Vue.extend({
async onSubmit() {
if (this.wait) return;
- const q = this.q.trim();
- if (q.startsWith('@')) {
- this.$router.push(`/${q}`);
- } else if (q.startsWith('#')) {
- this.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
- } else if (q.startsWith('https://')) {
- this.wait = true;
- try {
- const res = await this.$root.api('ap/show', {
- uri: q
- });
- if (res.type == 'User') {
- this.$router.push(`/@${res.object.username}@${res.object.host}`);
- } else if (res.type == 'Note') {
- this.$router.push(`/notes/${res.object.id}`);
- }
- } catch (e) {
- // TODO
- }
+ this.wait = true;
+ search(this, this.q).finally(() => {
this.wait = false;
- } else {
- this.$router.push(`/search?q=${encodeURIComponent(q)}`);
- }
+ this.q = '';
+ });
}
}
});
diff --git a/src/client/app/desktop/views/home/timeline.core.vue b/src/client/app/desktop/views/home/timeline.core.vue
index 12806365d4..654a1cc434 100644
--- a/src/client/app/desktop/views/home/timeline.core.vue
+++ b/src/client/app/desktop/views/home/timeline.core.vue
@@ -53,6 +53,12 @@ export default Vue.extend({
},
created() {
+ this.$root.$on('warp', this.warp);
+ this.$once('hook:beforeDestroy', () => {
+ this.$root.$off('warp', this.warp);
+ this.connection.dispose();
+ });
+
const prepend = note => {
(this.$refs.timeline as any).prepend(note);
};
@@ -124,13 +130,14 @@ export default Vue.extend({
});
},
- beforeDestroy() {
- this.connection.dispose();
- },
-
methods: {
focus() {
(this.$refs.timeline as any).focus();
+ },
+
+ warp(date) {
+ this.date = date;
+ (this.$refs.timeline as any).reload();
}
}
});
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index 4b9f341612..230d8c3f1e 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -458,10 +458,14 @@ export default (callback: (launch: (router: VueRouter) => [Vue, MiOS], os: MiOS)
},
dialog(opts) {
const vm = this.new(Dialog, opts);
- return new Promise((res) => {
+ const p: any = new Promise((res) => {
vm.$once('ok', result => res({ canceled: false, result }));
vm.$once('cancel', () => res({ canceled: true }));
});
+ p.close = () => {
+ vm.close();
+ };
+ return p;
}
},
router,
diff --git a/src/client/app/mobile/views/components/ui.nav.vue b/src/client/app/mobile/views/components/ui.nav.vue
index 169c7fc07d..b26e2380ab 100644
--- a/src/client/app/mobile/views/components/ui.nav.vue
+++ b/src/client/app/mobile/views/components/ui.nav.vue
@@ -66,6 +66,7 @@ import i18n from '../../../i18n';
import { lang } from '../../../config';
import { faNewspaper, faHashtag, faHome, faColumns } from '@fortawesome/free-solid-svg-icons';
import { faMoon, faSun } from '@fortawesome/free-regular-svg-icons';
+import { search } from '../../../common/scripts/search';
export default Vue.extend({
i18n: i18n('mobile/views/components/ui.nav.vue'),
@@ -133,29 +134,10 @@ export default Vue.extend({
}).then(async ({ canceled, result: query }) => {
if (canceled) return;
- const q = query.trim();
- if (q.startsWith('@')) {
- this.$router.push(`/${q}`);
- } else if (q.startsWith('#')) {
- this.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
- } else if (q.startsWith('https://')) {
- this.searching = true;
- try {
- const res = await this.$root.api('ap/show', {
- uri: q
- });
- if (res.type == 'User') {
- this.$router.push(`/@${res.object.username}@${res.object.host}`);
- } else if (res.type == 'Note') {
- this.$router.push(`/notes/${res.object.id}`);
- }
- } catch (e) {
- // TODO
- }
+ this.searching = true;
+ search(this, query).finally(() => {
this.searching = false;
- } else {
- this.$router.push(`/search?q=${encodeURIComponent(q)}`);
- }
+ });
});
},
diff --git a/src/client/app/mobile/views/pages/home.timeline.vue b/src/client/app/mobile/views/pages/home.timeline.vue
index 809158dd29..e0754e88b4 100644
--- a/src/client/app/mobile/views/pages/home.timeline.vue
+++ b/src/client/app/mobile/views/pages/home.timeline.vue
@@ -54,6 +54,12 @@ export default Vue.extend({
},
created() {
+ this.$root.$on('warp', this.warp);
+ this.$once('hook:beforeDestroy', () => {
+ this.$root.$off('warp', this.warp);
+ this.connection.dispose();
+ });
+
const prepend = note => {
(this.$refs.timeline as any).prepend(note);
};
@@ -125,10 +131,6 @@ export default Vue.extend({
});
},
- beforeDestroy() {
- this.connection.dispose();
- },
-
methods: {
focus() {
(this.$refs.timeline as any).focus();