1
1
<template >
2
2
<div class =" " >
3
3
<section class =" _section" >
4
- <div class =" _title" v-if =" title" >{{ title }}</div >
5
4
<div class =" _content" >
6
- <XPostForm v-if =" !posted" fixed :instant =" true" :initial-text =" initialText" @posted =" posted = true" class =" _panel" />
7
- <MkButton v-else primary @click =" close()" >{{ $ts.close }}</MkButton >
5
+ <XPostForm
6
+ v-if =" state === 'writing'"
7
+ fixed
8
+ :share =" true"
9
+ :initial-text =" initialText"
10
+ :initial-visibility =" visibility"
11
+ :initial-files =" files"
12
+ :initial-local-only =" localOnly"
13
+ :reply =" reply"
14
+ :renote =" renote"
15
+ :visible-users =" visibleUsers"
16
+ @posted =" state = 'posted'"
17
+ class =" _panel"
18
+ />
19
+ <MkButton v-else-if =" state === 'posted'" primary @click =" close()" class =" close" >{{ $ts.close }}</MkButton >
8
20
</div >
9
- <div class =" _footer" v-if =" url" >{{ url }}</div >
10
21
</section >
11
22
</div >
12
23
</template >
13
24
14
25
<script lang="ts">
26
+ // SPECIFICATION: /src/docs/ja-JP/advanced/share-page.md
27
+
15
28
import { defineComponent } from ' vue' ;
16
29
import MkButton from ' @client/components/ui/button.vue' ;
17
30
import XPostForm from ' @client/components/post-form.vue' ;
18
31
import * as os from ' @client/os' ;
32
+ import { noteVisibilities } from ' @/types' ;
33
+ import { parseAcct } from ' @/misc/acct' ;
19
34
import * as symbols from ' @client/symbols' ;
35
+ import * as Misskey from ' misskey-js' ;
20
36
21
37
export default defineComponent ({
22
38
components: {
@@ -30,35 +46,139 @@ export default defineComponent({
30
46
title: this .$ts .share ,
31
47
icon: ' fas fa-share-alt'
32
48
},
33
- title: null ,
34
- text: null ,
35
- url: null ,
36
- initialText: null ,
37
- posted: false ,
49
+ state: ' fetching' as ' fetching' | ' writing' | ' posted' ,
38
50
51
+ title: null as string | null ,
52
+ initialText: null as string | null ,
53
+ reply: null as Misskey .entities .Note | null ,
54
+ renote: null as Misskey .entities .Note | null ,
55
+ visibility: null as string | null ,
56
+ localOnly: null as boolean | null ,
57
+ files: [] as Misskey .entities .DriveFile [],
58
+ visibleUsers: [] as Misskey .entities .User [],
39
59
}
40
60
},
41
61
42
- created() {
62
+ async created() {
43
63
const urlParams = new URLSearchParams (window .location .search );
64
+
44
65
this .title = urlParams .get (' title' );
45
- this .text = urlParams .get (' text' );
46
- this .url = urlParams .get (' url' );
47
-
48
- let text = ' ' ;
49
- if (this .title ) text += ` 【${this .title }】\n ` ;
50
- if (this .text ) text += ` ${this .text }\n ` ;
51
- if (this .url ) text += ` ${this .url } ` ;
52
- this .initialText = text .trim ();
66
+ const text = urlParams .get (' text' );
67
+ const url = urlParams .get (' url' );
68
+
69
+ let noteText = ' ' ;
70
+ if (this .title ) noteText += ` [ ${this .title } ]\n ` ;
71
+ // Googleニュース対策
72
+ if (text ?.startsWith (` ${this .title }.\n ` )) noteText += text .replace (` ${this .title }.\n ` , ' ' );
73
+ else if (text && this .title !== text ) noteText += ` ${text }\n ` ;
74
+ if (url ) noteText += ` ${url } ` ;
75
+ this .initialText = noteText .trim ();
76
+
77
+ const visibility = urlParams .get (' visibility' );
78
+ if (noteVisibilities .includes (visibility )) {
79
+ this .visibility = visibility ;
80
+ }
81
+
82
+ if (this .visibility === ' specified' ) {
83
+ const visibleUserIds = urlParams .get (' visibleUserIds' );
84
+ const visibleAccts = urlParams .get (' visibleAccts' );
85
+ await Promise .all (
86
+ [
87
+ ... (visibleUserIds ? visibleUserIds .split (' ,' ).map (userId => ({ userId })) : []),
88
+ ... (visibleAccts ? visibleAccts .split (' ,' ).map (parseAcct ) : [])
89
+ ]
90
+ // TypeScriptの指示通りに変換する
91
+ .map (q => ' username' in q ? { username: q .username , host: q .host === null ? undefined : q .host } : q )
92
+ .map (q => os .api (' users/show' , q )
93
+ .then (user => {
94
+ this .visibleUsers .push (user );
95
+ }, () => {
96
+ console .error (` Invalid user query: ${JSON .stringify (q )} ` );
97
+ })
98
+ )
99
+ );
100
+ }
101
+
102
+ const localOnly = urlParams .get (' localOnly' );
103
+ if (localOnly === ' 0' ) this .localOnly = false ;
104
+ else if (localOnly === ' 1' ) this .localOnly = true ;
105
+
106
+ try {
107
+ // #region Reply
108
+ const replyId = urlParams .get (' replyId' );
109
+ const replyUri = urlParams .get (' replyUri' );
110
+ if (replyId ) {
111
+ this .reply = await os .api (' notes/show' , {
112
+ noteId: replyId
113
+ });
114
+ } else if (replyUri ) {
115
+ const obj = await os .api (' ap/show' , {
116
+ uri: replyUri
117
+ });
118
+ if (obj .type === ' Note' ) {
119
+ this .reply = obj .object ;
120
+ }
121
+ }
122
+ // #endregion
123
+
124
+ // #region Renote
125
+ const renoteId = urlParams .get (' renoteId' );
126
+ const renoteUri = urlParams .get (' renoteUri' );
127
+ if (renoteId ) {
128
+ this .renote = await os .api (' notes/show' , {
129
+ noteId: renoteId
130
+ });
131
+ } else if (renoteUri ) {
132
+ const obj = await os .api (' ap/show' , {
133
+ uri: renoteUri
134
+ });
135
+ if (obj .type === ' Note' ) {
136
+ this .renote = obj .object ;
137
+ }
138
+ }
139
+ // #endregion
140
+
141
+ // #region Drive files
142
+ const fileIds = urlParams .get (' fileIds' );
143
+ if (fileIds ) {
144
+ await Promise .all (
145
+ fileIds .split (' ,' )
146
+ .map (fileId => os .api (' drive/files/show' , { fileId })
147
+ .then (file => {
148
+ this .files .push (file );
149
+ }, () => {
150
+ console .error (` Failed to fetch a file ${fileId } ` );
151
+ })
152
+ )
153
+ );
154
+ }
155
+ // #endregion
156
+ } catch (e ) {
157
+ os .dialog ({
158
+ type: ' error' ,
159
+ title: e .message ,
160
+ text: e .name
161
+ });
162
+ }
163
+
164
+ this .state = ' writing' ;
53
165
},
54
166
55
167
methods: {
56
168
close() {
57
- window .close ()
169
+ window .close ();
170
+
171
+ // 閉じなければ100ms後タイムラインに
172
+ setTimeout (() => {
173
+ this .$router .push (' /' );
174
+ }, 100 );
58
175
}
59
176
}
60
177
});
61
178
</script >
62
179
63
180
<style lang="scss" scoped>
181
+ .close {
182
+ margin : 16px auto ;
183
+ }
64
184
</style >
0 commit comments