From 4628f507e5209b560813578e86ebdc1ca747eda3 Mon Sep 17 00:00:00 2001
From: Satsuki Yanagi <17376330+u1-liquid@users.noreply.github.com>
Date: Sun, 7 Jul 2019 17:14:08 +0900
Subject:
公開以外へのリプライ時元の公開範囲で指定したユーザー情報を引き継ぐように
(#5119)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 公開以外へのリプライ時元の公開範囲で指定したユーザー情報を引き継ぐように
* Use users/show userIds
---
src/client/app/common/scripts/post-form.ts | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
(limited to 'src/client/app/common/scripts')
diff --git a/src/client/app/common/scripts/post-form.ts b/src/client/app/common/scripts/post-form.ts
index 85a578484f..7cd2e7c310 100644
--- a/src/client/app/common/scripts/post-form.ts
+++ b/src/client/app/common/scripts/post-form.ts
@@ -151,9 +151,16 @@ export default (opts) => ({
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
if (this.reply && ['home', 'followers', 'specified'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility;
+ if (this.reply.visibility === 'specified') {
+ this.$root.api('users/show', {
+ userIds: this.reply.visibleUserIds.filter(uid => uid !== this.$store.state.i.id && uid !== this.reply.userId)
+ }).then(users => {
+ this.visibleUsers.push(...users);
+ });
+ }
}
- if (this.reply) {
+ if (this.reply && this.reply.userId !== this.$store.state.i.id) {
this.$root.api('users/show', { userId: this.reply.userId }).then(user => {
this.visibleUsers.push(user);
});
--
cgit v1.2.3-freya
From 841c8d619fceb99b4494e7d62c2cd8594f72bdf2 Mon Sep 17 00:00:00 2001
From: syuilo
Date: Mon, 8 Jul 2019 04:17:53 +0900
Subject: 既定のアップロード先フォルダを設定できるように
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
locales/ja-JP.yml | 8 +++++-
src/client/app/common/scripts/post-form.ts | 2 +-
.../views/components/messaging-room.form.vue | 2 +-
.../app/common/views/components/settings/drive.vue | 33 ++++++++++++++++++++--
src/client/app/common/views/widgets/post-form.vue | 2 +-
.../app/desktop/views/components/drive.folder.vue | 33 +++++++++++++++++++++-
src/client/app/store.ts | 1 +
7 files changed, 74 insertions(+), 7 deletions(-)
(limited to 'src/client/app/common/scripts')
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 637f2235d6..6b008a3df8 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -958,7 +958,7 @@ desktop/views/components/drive.file.vue:
unmark-as-sensitive: "閲覧注意を解除"
copy-url: "URLをコピー"
download: "ダウンロード"
- else-files: "その他..."
+ else-files: "その他"
set-as-avatar: "アイコンに設定"
set-as-banner: "バナーに設定"
open-in-app: "アプリで開く"
@@ -969,6 +969,7 @@ desktop/views/components/drive.file.vue:
copied-url-to-clipboard: "URLをクリップボードにコピーしました"
desktop/views/components/drive.folder.vue:
+ upload-folder: "既定アップロード先"
unable-to-process: "操作を完了できません"
circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
unhandled-error: "不明なエラー"
@@ -980,6 +981,8 @@ desktop/views/components/drive.folder.vue:
rename: "名前を変更"
rename-folder: "フォルダ名の変更"
input-new-folder-name: "新しいフォルダ名を入力してください"
+ else-folders: "その他"
+ set-as-upload-folder: "既定アップロード先に設定"
desktop/views/components/drive.vue:
search: "検索"
@@ -1143,6 +1146,9 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
+ default-upload-folder: "既定のアップロード先フォルダ"
+ default-upload-folder-name: "フォルダ"
+ change-default-upload-folder: "フォルダを変更"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
diff --git a/src/client/app/common/scripts/post-form.ts b/src/client/app/common/scripts/post-form.ts
index 7cd2e7c310..1d93b4c268 100644
--- a/src/client/app/common/scripts/post-form.ts
+++ b/src/client/app/common/scripts/post-form.ts
@@ -245,7 +245,7 @@ export default (opts) => ({
},
upload(file) {
- (this.$refs.uploader as any).upload(file);
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
},
onChangeUploadings(uploads) {
diff --git a/src/client/app/common/views/components/messaging-room.form.vue b/src/client/app/common/views/components/messaging-room.form.vue
index 1dfb0589e4..74e30d29e8 100644
--- a/src/client/app/common/views/components/messaging-room.form.vue
+++ b/src/client/app/common/views/components/messaging-room.form.vue
@@ -158,7 +158,7 @@ export default Vue.extend({
},
upload(file) {
- (this.$refs.uploader as any).upload(file);
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
},
onUploaded(file) {
diff --git a/src/client/app/common/views/components/settings/drive.vue b/src/client/app/common/views/components/settings/drive.vue
index 7bdc806ae7..9b049c98e3 100644
--- a/src/client/app/common/views/components/settings/drive.vue
+++ b/src/client/app/common/views/components/settings/drive.vue
@@ -11,6 +11,12 @@
+
+
+ {{ $t('default-upload-folder') }}
+ {{ $t('default-upload-folder-name') }}
+ {{ $t('change-default-upload-folder') }}
+
@@ -26,7 +32,8 @@ export default Vue.extend({
return {
fetching: true,
usage: null,
- capacity: null
+ capacity: null,
+ uploadFolderName: null
};
},
@@ -40,10 +47,25 @@ export default Vue.extend({
l: 0.5
})
};
- }
+ },
+
+ uploadFolder: {
+ get() { return this.$store.state.settings.uploadFolder; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'uploadFolder', value }); }
+ },
},
mounted() {
+ if (this.uploadFolder == null) {
+ this.uploadFolderName = this.$t('@._settings.root');
+ } else {
+ this.$root.api('drive/folders/show', {
+ folderId: this.uploadFolder
+ }).then(folder => {
+ this.uploadFolderName = folder.name;
+ });
+ }
+
this.$root.api('drive').then(info => {
this.capacity = info.capacity;
this.usage = info.usage;
@@ -152,6 +174,13 @@ export default Vue.extend({
chart.render();
});
+ },
+
+ chooseUploadFolder() {
+ this.$chooseDriveFolder().then(folder => {
+ this.uploadFolder = folder ? folder.id : null;
+ this.uploadFolderName = folder ? folder.name : this.$t('@._settings.root');
+ })
}
}
});
diff --git a/src/client/app/common/views/widgets/post-form.vue b/src/client/app/common/views/widgets/post-form.vue
index e180290f95..5e577c9a43 100644
--- a/src/client/app/common/views/widgets/post-form.vue
+++ b/src/client/app/common/views/widgets/post-form.vue
@@ -122,7 +122,7 @@ export default define({
},
upload(file) {
- (this.$refs.uploader as any).upload(file);
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
},
onDragover(e) {
diff --git a/src/client/app/desktop/views/components/drive.folder.vue b/src/client/app/desktop/views/components/drive.folder.vue
index bc74ed4317..cf59d51b01 100644
--- a/src/client/app/desktop/views/components/drive.folder.vue
+++ b/src/client/app/desktop/views/components/drive.folder.vue
@@ -20,6 +20,9 @@
{{ folder.name }}
+
+ {{ $t('upload-folder') }}
+
@@ -73,6 +76,14 @@ export default Vue.extend({
text: this.$t('@.delete'),
icon: ['far', 'trash-alt'],
action: this.deleteFolder
+ }, null, {
+ type: 'nest',
+ text: this.$t('contextmenu.else-folders'),
+ menu: [{
+ type: 'item',
+ text: this.$t('contextmenu.set-as-upload-folder'),
+ action: this.setAsUploadFolder
+ }]
}], {
closed: () => {
this.isContextmenuShowing = false;
@@ -213,6 +224,13 @@ export default Vue.extend({
deleteFolder() {
this.$root.api('drive/folders/delete', {
folderId: this.folder.id
+ }).then(() => {
+ if (this.$store.state.settings.uploadFolder === this.folder.id) {
+ this.$store.dispatch('settings/set', {
+ key: 'uploadFolder',
+ value: null
+ });
+ }
}).catch(err => {
switch(err.id) {
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
@@ -229,7 +247,14 @@ export default Vue.extend({
});
}
});
- }
+ },
+
+ setAsUploadFolder() {
+ this.$store.dispatch('settings/set', {
+ key: 'uploadFolder',
+ value: this.folder.id
+ });
+ },
}
});
@@ -279,4 +304,10 @@ export default Vue.extend({
margin-left 2px
text-align left
+ > .upload
+ margin 4px 4px
+ font-size 0.8em
+ text-align right
+ color var(--desktopDriveFolderFg)
+
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 852d2c393d..f5c89e24f6 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -38,6 +38,7 @@ const defaultSettings = {
homeProfiles: {},
mobileHomeProfiles: {},
deckProfiles: {},
+ uploadFolder: null,
};
const defaultDeviceSettings = {
--
cgit v1.2.3-freya
From 5343b005df9446c3cc13bdfb419db9b8720e5946 Mon Sep 17 00:00:00 2001
From: tamaina
Date: Mon, 8 Jul 2019 13:46:31 +0900
Subject: Improve paste uploading Resolve #3023 (#4542)
* resolve #3023
* fix
* fix
* better description
* widget
* fix text
* Update post-form.vue
* Fix enter-file-name dialog title text
* Fix type
* On messaging room
* Replace moment.js to original one
* Fix formatDateTimeString
---
locales/ja-JP.yml | 6 +++
src/client/app/common/scripts/post-form.ts | 24 ++++++++---
.../views/components/messaging-room.form.vue | 22 ++++++++--
.../common/views/components/settings/settings.vue | 24 ++++++++++-
.../app/common/views/components/uploader.vue | 5 ++-
src/client/app/common/views/widgets/post-form.vue | 24 ++++++++---
src/client/app/store.ts | 2 +
src/misc/format-time-string.ts | 50 ++++++++++++++++++++++
src/server/api/endpoints/drive/files/create.ts | 10 ++++-
test/api.ts | 14 ++++++
10 files changed, 163 insertions(+), 18 deletions(-)
create mode 100644 src/misc/format-time-string.ts
(limited to 'src/client/app/common/scripts')
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index bf23e44705..d2776c45b1 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -129,6 +129,7 @@ common:
add-visible-user: "ユーザーを追加"
cw-placeholder: "内容への注釈 (オプション)"
username-prompt: "ユーザー名を入力してください"
+ enter-file-name: "ファイル名を編集"
weekday-short:
sunday: "日"
@@ -201,6 +202,11 @@ common:
remember-note-visibility: "投稿の公開範囲を記憶する"
web-search-engine: "ウェブ検索エンジン"
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
+ paste: "ペースト"
+ pasted-file-name: "ペーストされたファイル名のテンプレート"
+ pasted-file-name-desc: "例: \"yyyy-MM-dd HH-mm-ss [{{number}}]\" → \"2018-03-20 21-30-24 1\""
+ paste-dialog: "ペースト時にファイル名を編集"
+ paste-dialog-desc: "ペースト時にファイル名を編集するダイアログを表示するようにします。"
keep-cw: "CW保持"
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
diff --git a/src/client/app/common/scripts/post-form.ts b/src/client/app/common/scripts/post-form.ts
index 1d93b4c268..7cf26f65bf 100644
--- a/src/client/app/common/scripts/post-form.ts
+++ b/src/client/app/common/scripts/post-form.ts
@@ -8,6 +8,7 @@ import { host, url } from '../../config';
import i18n from '../../i18n';
import { erase, unique } from '../../../../prelude/array';
import extractMentions from '../../../../misc/extract-mentions';
+import { formatTimeString } from '../../../../misc/format-time-string';
export default (opts) => ({
i18n: i18n(),
@@ -244,8 +245,8 @@ export default (opts) => ({
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onChangeUploadings(uploads) {
@@ -334,10 +335,23 @@ export default (opts) => ({
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canPost) this.post();
},
- async onPaste(e) {
- for (const item of Array.from(e.clipboardData.items)) {
+ async onPaste(e: ClipboardEvent) {
+ for (const { item, i } of Array.from(e.clipboardData.items).map((item, i) => ({item, i}))) {
if (item.kind == 'file') {
- this.upload(item.getAsFile());
+ const file = item.getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, `${i + 1}`)}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
}
diff --git a/src/client/app/common/views/components/messaging-room.form.vue b/src/client/app/common/views/components/messaging-room.form.vue
index 74e30d29e8..bd63bab2c1 100644
--- a/src/client/app/common/views/components/messaging-room.form.vue
+++ b/src/client/app/common/views/components/messaging-room.form.vue
@@ -30,6 +30,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import * as autosize from 'autosize';
+import { formatTimeString } from '../../../../../misc/format-time-string';
export default Vue.extend({
i18n: i18n('common/views/components/messaging-room.form.vue'),
@@ -84,13 +85,26 @@ export default Vue.extend({
}
},
methods: {
- onPaste(e) {
+ async onPaste(e: ClipboardEvent) {
const data = e.clipboardData;
const items = data.items;
if (items.length == 1) {
if (items[0].kind == 'file') {
- this.upload(items[0].getAsFile());
+ const file = items[0].getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, '1')}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
} else {
if (items[0].kind == 'file') {
@@ -157,8 +171,8 @@ export default Vue.extend({
this.upload((this.$refs.file as any).files[0]);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onUploaded(file) {
diff --git a/src/client/app/common/views/components/settings/settings.vue b/src/client/app/common/views/components/settings/settings.vue
index 5f370c8be7..281524979e 100644
--- a/src/client/app/common/views/components/settings/settings.vue
+++ b/src/client/app/common/views/components/settings/settings.vue
@@ -140,7 +140,19 @@
{{ $t('@._settings.web-search-engine') }}
- {{ $t('@._settings.web-search-engine') }}{{ $t('@._settings.web-search-engine-desc') }}
+ {{ $t('@._settings.web-search-engine') }}
+ {{ $t('@._settings.web-search-engine-desc') }}
+
+
+
+
+ {{ $t('@._settings.paste') }}
+ {{ $t('@._settings.pasted-file-name') }}
+ {{ $t('@._settings.pasted-file-name-desc') }}
+
+ {{ $t('@._settings.paste-dialog') }}
+ {{ $t('@._settings.paste-dialog-desc') }}
+
@@ -412,6 +424,16 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'webSearchEngine', value }); }
},
+ pastedFileName: {
+ get() { return this.$store.state.settings.pastedFileName; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'pastedFileName', value }); }
+ },
+
+ pasteDialog: {
+ get() { return this.$store.state.settings.pasteDialog; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'pasteDialog', value }); }
+ },
+
showReplyTarget: {
get() { return this.$store.state.settings.showReplyTarget; },
set(value) { this.$store.dispatch('settings/set', { key: 'showReplyTarget', value }); }
diff --git a/src/client/app/common/views/components/uploader.vue b/src/client/app/common/views/components/uploader.vue
index 78fbcbf6b8..9f02da6c1e 100644
--- a/src/client/app/common/views/components/uploader.vue
+++ b/src/client/app/common/views/components/uploader.vue
@@ -46,7 +46,7 @@ export default Vue.extend({
});
},
- upload(file: File, folder: any) {
+ upload(file: File, folder: any, name?: string) {
if (folder && typeof folder == 'object') folder = folder.id;
const id = Math.random();
@@ -61,7 +61,7 @@ export default Vue.extend({
const ctx = {
id: id,
- name: file.name || 'untitled',
+ name: name || file.name || 'untitled',
progress: undefined,
img: window.URL.createObjectURL(file)
};
@@ -75,6 +75,7 @@ export default Vue.extend({
data.append('file', file);
if (folder) data.append('folderId', folder);
+ if (name) data.append('name', name);
const xhr = new XMLHttpRequest();
xhr.open('POST', apiUrl + '/drive/files/create', true);
diff --git a/src/client/app/common/views/widgets/post-form.vue b/src/client/app/common/views/widgets/post-form.vue
index 5e577c9a43..6680a11435 100644
--- a/src/client/app/common/views/widgets/post-form.vue
+++ b/src/client/app/common/views/widgets/post-form.vue
@@ -38,6 +38,7 @@
import define from '../../../common/define-widget';
import i18n from '../../../i18n';
import insertTextAtCursor from 'insert-text-at-cursor';
+import { formatTimeString } from '../../../../../misc/format-time-string';
export default define({
name: 'post-form',
@@ -109,10 +110,23 @@ export default define({
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && !this.posting && this.text) this.post();
},
- onPaste(e) {
- for (const item of Array.from(e.clipboardData.items)) {
+ async onPaste(e: ClipboardEvent) {
+ for (const { item, i } of Array.from(e.clipboardData.items).map((item, i) => ({item, i}))) {
if (item.kind == 'file') {
- this.upload(item.getAsFile());
+ const file = item.getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, `${i + 1}`)}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
}
},
@@ -121,8 +135,8 @@ export default define({
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onDragover(e) {
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 252feb3982..18137c1ca9 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -39,6 +39,8 @@ const defaultSettings = {
mobileHomeProfiles: {},
deckProfiles: {},
uploadFolder: null,
+ pastedFileName: 'yyyy-MM-dd HH-mm-ss [{{number}}]',
+ pasteDialog: false,
};
const defaultDeviceSettings = {
diff --git a/src/misc/format-time-string.ts b/src/misc/format-time-string.ts
new file mode 100644
index 0000000000..4729036e5b
--- /dev/null
+++ b/src/misc/format-time-string.ts
@@ -0,0 +1,50 @@
+const defaultLocaleStringFormats: {[index: string]: string} = {
+ 'weekday': 'narrow',
+ 'era': 'narrow',
+ 'year': 'numeric',
+ 'month': 'numeric',
+ 'day': 'numeric',
+ 'hour': 'numeric',
+ 'minute': 'numeric',
+ 'second': 'numeric',
+ 'timeZoneName': 'short'
+};
+
+function formatLocaleString(date: Date, format: string): string {
+ return format.replace(/\{\{(\w+)(:(\w+))?\}\}/g, (match: string, kind: string, unused?, option?: string) => {
+ if (['weekday', 'era', 'year', 'month', 'day', 'hour', 'minute', 'second', 'timeZoneName'].includes(kind)) {
+ return date.toLocaleString(window.navigator.language, {[kind]: option ? option : defaultLocaleStringFormats[kind]});
+ } else {
+ return match;
+ }
+ });
+}
+
+function formatDateTimeString(date: Date, format: string): string {
+ return format
+ .replace(/yyyy/g, date.getFullYear().toString())
+ .replace(/yy/g, date.getFullYear().toString().slice(-2))
+ .replace(/MMMM/g, date.toLocaleString(window.navigator.language, { month: 'long'}))
+ .replace(/MMM/g, date.toLocaleString(window.navigator.language, { month: 'short'}))
+ .replace(/MM/g, (`0${date.getMonth() + 1}`).slice(-2))
+ .replace(/M/g, (date.getMonth() + 1).toString())
+ .replace(/dd/g, (`0${date.getDate()}`).slice(-2))
+ .replace(/d/g, date.getDate().toString())
+ .replace(/HH/g, (`0${date.getHours()}`).slice(-2))
+ .replace(/H/g, date.getHours().toString())
+ .replace(/hh/g, (`0${(date.getHours() % 12) || 12}`).slice(-2))
+ .replace(/h/g, ((date.getHours() % 12) || 12).toString())
+ .replace(/mm/g, (`0${date.getMinutes()}`).slice(-2))
+ .replace(/m/g, date.getMinutes().toString())
+ .replace(/ss/g, (`0${date.getSeconds()}`).slice(-2))
+ .replace(/s/g, date.getSeconds().toString())
+ .replace(/tt/g, date.getHours() >= 12 ? 'PM' : 'AM');
+}
+
+export function formatTimeString(date: Date, format: string): string {
+ return format.replace(/\[(([^\[]|\[\])*)\]|([yMdHhmst]{1,4})/g, (match: string, localeformat?: string, unused?, datetimeformat?: string) => {
+ if (localeformat) return formatLocaleString(date, localeformat);
+ if (datetimeformat) return formatDateTimeString(date, datetimeformat);
+ return match;
+ });
+}
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index 664a2b87b2..61055c5d18 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -35,6 +35,14 @@ export const meta = {
}
},
+ name: {
+ validator: $.optional.nullable.str,
+ default: null as any,
+ desc: {
+ 'ja-JP': 'ファイル名(拡張子があるなら含めて)'
+ }
+ },
+
isSensitive: {
validator: $.optional.either($.bool, $.str),
default: false,
@@ -72,7 +80,7 @@ export const meta = {
export default define(meta, async (ps, user, app, file, cleanup) => {
// Get 'name' parameter
- let name = file.originalname;
+ let name = ps.name || file.originalname;
if (name !== undefined && name !== null) {
name = name.trim();
if (name.length === 0) {
diff --git a/test/api.ts b/test/api.ts
index 570ab6833d..343112b4aa 100644
--- a/test/api.ts
+++ b/test/api.ts
@@ -474,6 +474,20 @@ describe('API', () => {
assert.strictEqual(res.body.name, 'Lenna.png');
}));
+ it('ファイルに名前を付けられる', async(async () => {
+ const alice = await signup({ username: 'alice' });
+
+ const res = await assert.request(server)
+ .post('/drive/files/create')
+ .field('i', alice.token)
+ .field('name', 'Belmond.png')
+ .attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png');
+
+ expect(res).have.status(200);
+ expect(res.body).be.a('object');
+ expect(res.body).have.property('name').eql('Belmond.png');
+ }));
+
it('ファイル無しで怒られる', async(async () => {
const alice = await signup({ username: 'alice' });
--
cgit v1.2.3-freya