Compare commits

...

13 Commits

Author SHA1 Message Date
7a406c1f13 Docker (#2867)
* Dockerize Misskey

* Add a new line at EOF

* Add support Elasticsearch

* /

* Add setup document for docker

* Add english document

* Edit docs

* docker -> Docker

* Arrange format

* Update docker.en.md

* Modify title
2018-10-09 15:09:50 +09:00
9432af2ab5 10.3.0 2018-10-09 15:09:24 +09:00
136b13e7ca Fix bug and refactor 2018-10-09 15:08:31 +09:00
ba1c823fb1 🎨 2018-10-09 14:58:37 +09:00
f1301a4780 fix(package): update @types/redis to version 2.8.7 (#2866) 2018-10-09 09:38:47 +09:00
7957cd4963 fix(package): update @types/node to version 10.11.5 (#2865) 2018-10-09 09:38:40 +09:00
ee6590d03f fix(package): update @types/mongodb to version 3.1.11 (#2864) 2018-10-09 09:38:31 +09:00
f2a1238b20 fix(package): update commander to version 2.19.0 (#2862) 2018-10-09 09:38:21 +09:00
c464183329 Improve theme manager 2018-10-09 06:46:52 +09:00
389f420cad Update src/tools/move-drive-files.ts 2018-10-09 05:46:21 +09:00
6b2888383c 10.2.1 2018-10-09 05:36:39 +09:00
3c38a867b4 Fix bug 2018-10-09 05:35:40 +09:00
7f5a69f4d8 Fix bug 2018-10-09 05:31:26 +09:00
26 changed files with 374 additions and 132 deletions

View File

@ -0,0 +1,13 @@
var user = {
user: 'example-misskey-user',
pwd: 'example-misskey-pass',
roles: [
{
role: 'readWrite',
db: 'misskey'
}
]
};
db.createUser(user);

12
.dockerignore Executable file
View File

@ -0,0 +1,12 @@
.autogen
.git
.github
.travis
.vscode
Dockerfile
build/
docker-compose.yml
node_modules/
mongo/
redis/
elasticsearch/

4
.gitignore vendored
View File

@ -1,5 +1,6 @@
/.config/* /.config/*
!/.config/example.yml !/.config/example.yml
!/.config/mongo_initdb_example.js
/.vscode /.vscode
/node_modules /node_modules
/build /build
@ -12,3 +13,6 @@ npm-debug.log
run.bat run.bat
api-docs.json api-docs.json
*.log *.log
/redis
/mongo
/elasticsearch

28
Dockerfile Normal file
View File

@ -0,0 +1,28 @@
FROM alpine:latest AS base
ENV NODE_ENV=production
RUN apk add --no-cache nodejs nodejs-npm
RUN apk add vips fftw --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
WORKDIR /misskey
COPY . ./
FROM base AS builder
RUN apk add --no-cache gcc g++ python autoconf automake file make nasm
RUN apk add vips-dev fftw-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
RUN npm install \
&& npm install -g node-gyp \
&& node-gyp configure \
&& node-gyp build \
&& npm run build
FROM base AS runner
COPY --from=builder /misskey/built ./built
COPY --from=builder /misskey/node_modules ./node_modules
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["npm", "start"]

52
docker-compose.yml Normal file
View File

@ -0,0 +1,52 @@
version: "3"
services:
web:
build: .
restart: always
links:
- mongo
- redis
# - es
ports:
- "127.0.0.1:3000:3000"
networks:
- internal_network
- external_network
redis:
restart: always
image: redis:4.0-alpine
networks:
- internal_network
### Uncomment to enable Redis persistance
# volumes:
# - ./redis:/data
mongo:
restart: always
image: mongo:4.1-bionic
networks:
- internal_network
environment:
MONGO_INITDB_DATABASE: "misskey"
volumes:
- ./.config/mongo_initdb.js:/docker-entrypoint-initdb.d/mongo_initdb.js:ro
### Uncomment to enable MongoDB persistance
# - ./mongo:/data
# es:
# restart: always
# image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.2
# environment:
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
# networks:
# - internal_network
#### Uncomment to enable ES persistence
## volumes:
## - ./elasticsearch:/usr/share/elasticsearch/data
networks:
internal_network:
internal: true
external_network:

47
docs/docker.en.md Normal file
View File

@ -0,0 +1,47 @@
Docker Guide
================================================================
This guide describes how to install and setup Misskey with Docker.
[Japanese version also available - 日本語版もあります](./docker.ja.md)
----------------------------------------------------------------
*1.* Make configuration files
----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`.
2. Edit `default.yml` and `mongo_initdb.js`.
*2.* Configure Docker
----------------------------------------------------------------
Edit `docker-compose.yml`.
*3.* Build Misskey
----------------------------------------------------------------
Build misskey with the following:
`docker-compose build`
*4.* That is it.
----------------------------------------------------------------
Well done! Now, you have an environment that run to Misskey.
### Launch normally
Just `docker-compose up -d`. GLHF!
### Way to Update to latest version of your Misskey
1. `git fetch`
2. `git stash`
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
4. `git stash pop`
5. `docker-compose build`
6. Check [ChangeLog](../CHANGELOG.md) for migration information
7. `docker-compose stop && docker-compose up -d`
### Way to execute cli command:
`docker-compose run --rm web node cli/mark-admin @example`
----------------------------------------------------------------
If you have any questions or troubles, feel free to contact us!

48
docs/docker.ja.md Normal file
View File

@ -0,0 +1,48 @@
Dockerを使ったMisskey構築方法
================================================================
このガイドはDockerを使ったMisskeyセットアップ方法について解説します。
[英語版もあります - English version also available](./docker.en.md)
----------------------------------------------------------------
*1.* 設定ファイルを作成する
----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` `.config/mongo_initdb_example.js`をコピーし名前を`mongo_initdb.js`にする
3. `default.yml``mongo_initdb.js`を編集する
*2.* Dockerの設定
----------------------------------------------------------------
`docker-compose.yml`を編集してください。
*3.* Misskeyのビルド
----------------------------------------------------------------
次のコマンドでMisskeyをビルドしてください:
`docker-compose build`
*4.* 以上です!
----------------------------------------------------------------
お疲れ様でした。これでMisskeyを動かす準備は整いました。
### 通常起動
`docker-compose up -d`するだけです。GLHF!
### Misskeyを最新バージョンにアップデートする方法:
1. `git fetch`
2. `git stash`
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
4. `git stash pop`
5. `docker-compose build`
6. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する
7. `docker-compose stop && docker-compose up -d`
### cliコマンドを実行する方法:
`docker-compose run --rm web node cli/mark-admin @example`
----------------------------------------------------------------
なにかお困りのことがありましたらお気軽にご連絡ください。

View File

@ -307,6 +307,9 @@ common/views/components/theme.vue:
invalid-theme: "テーマが正しくありません。" invalid-theme: "テーマが正しくありません。"
already-installed: "既にそのテーマはインストールされています。" already-installed: "既にそのテーマはインストールされています。"
saved: "保存しました" saved: "保存しました"
manage-themes: "テーマの管理"
builtin-themes: "標準テーマ"
my-themes: "マイテーマ"
installed-themes: "インストールされたテーマ" installed-themes: "インストールされたテーマ"
select-theme: "テーマを選択してください" select-theme: "テーマを選択してください"
uninstall: "アンインストール" uninstall: "アンインストール"

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "10.2.0", "version": "10.3.0",
"clientVersion": "1.0.10362", "clientVersion": "1.0.10375",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -58,14 +58,14 @@
"@types/minio": "7.0.0", "@types/minio": "7.0.0",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/mocha": "5.2.3", "@types/mocha": "5.2.3",
"@types/mongodb": "3.1.10", "@types/mongodb": "3.1.11",
"@types/ms": "0.7.30", "@types/ms": "0.7.30",
"@types/node": "10.11.4", "@types/node": "10.11.5",
"@types/portscanner": "2.1.0", "@types/portscanner": "2.1.0",
"@types/pug": "2.0.4", "@types/pug": "2.0.4",
"@types/qrcode": "1.3.0", "@types/qrcode": "1.3.0",
"@types/ratelimiter": "2.1.28", "@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.6", "@types/redis": "2.8.7",
"@types/request": "2.47.1", "@types/request": "2.47.1",
"@types/request-promise-native": "1.0.15", "@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2", "@types/rimraf": "2.0.2",
@ -92,7 +92,7 @@
"cafy": "11.3.0", "cafy": "11.3.0",
"chalk": "2.4.1", "chalk": "2.4.1",
"chart.js": "2.7.2", "chart.js": "2.7.2",
"commander": "2.17.1", "commander": "2.19.0",
"crc-32": "1.2.0", "crc-32": "1.2.0",
"css-loader": "1.0.0", "css-loader": "1.0.0",
"dateformat": "3.0.3", "dateformat": "3.0.3",
@ -219,6 +219,7 @@
"vue-router": "3.0.1", "vue-router": "3.0.1",
"vue-style-loader": "4.1.2", "vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.0", "vue-svg-inline-loader": "1.2.0",
"vue-sweetalert2": "1.5.5",
"vue-template-compiler": "2.5.17", "vue-template-compiler": "2.5.17",
"vuedraggable": "2.16.0", "vuedraggable": "2.16.0",
"vuewordcloud": "18.7.11", "vuewordcloud": "18.7.11",

View File

@ -130,3 +130,16 @@ pre
[data-fa] [data-fa]
display inline-block display inline-block
.swal2-popup
background var(--face) !important
.swal-icon-only
width 180px !important
> .swal2-header
> .swal2-icon
margin 1.25em auto 1.875em
> .swal2-title
display none

View File

@ -91,7 +91,11 @@ export default prop => ({
Vue.set(this.$_ns_target, 'reactionCounts', {}); Vue.set(this.$_ns_target, 'reactionCounts', {});
} }
this.$_ns_target.reactionCounts[reaction] = (this.$_ns_target.reactionCounts[reaction] || 0) + 1; if (this.$_ns_target.reactionCounts[reaction] == null) {
Vue.set(this.$_ns_target.reactionCounts, reaction, 0);
}
this.$_ns_target.reactionCounts[reaction]++;
if (body.userId == this.$store.state.i.id) { if (body.userId == this.$store.state.i.id) {
Vue.set(this.$_ns_target, 'myReaction', reaction); Vue.set(this.$_ns_target, 'myReaction', reaction);

View File

@ -26,92 +26,6 @@ export default class Stream extends EventEmitter {
this.stream.addEventListener('open', this.onOpen); this.stream.addEventListener('open', this.onOpen);
this.stream.addEventListener('close', this.onClose); this.stream.addEventListener('close', this.onClose);
this.stream.addEventListener('message', this.onMessage); this.stream.addEventListener('message', this.onMessage);
if (user) {
const main = this.useSharedConnection('main');
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
os.store.dispatch('mergeMe', i);
});
main.on('readAllNotifications', () => {
os.store.dispatch('mergeMe', {
hasUnreadNotification: false
});
});
main.on('unreadNotification', () => {
os.store.dispatch('mergeMe', {
hasUnreadNotification: true
});
});
main.on('readAllMessagingMessages', () => {
os.store.dispatch('mergeMe', {
hasUnreadMessagingMessage: false
});
});
main.on('unreadMessagingMessage', () => {
os.store.dispatch('mergeMe', {
hasUnreadMessagingMessage: true
});
});
main.on('unreadMention', () => {
os.store.dispatch('mergeMe', {
hasUnreadMentions: true
});
});
main.on('readAllUnreadMentions', () => {
os.store.dispatch('mergeMe', {
hasUnreadMentions: false
});
});
main.on('unreadSpecifiedNote', () => {
os.store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: true
});
});
main.on('readAllUnreadSpecifiedNotes', () => {
os.store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: false
});
});
main.on('clientSettingUpdated', x => {
os.store.commit('settings/set', {
key: x.key,
value: x.value
});
});
main.on('homeUpdated', x => {
os.store.commit('settings/setHome', x);
});
main.on('mobileHomeUpdated', x => {
os.store.commit('settings/setMobileHome', x);
});
main.on('widgetUpdated', x => {
os.store.commit('settings/setWidget', {
id: x.id,
data: x.data
});
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
alert('%i18n:common.my-token-regenerated%');
os.signout();
});
}
} }
public useSharedConnection = (channel: string): SharedConnection => { public useSharedConnection = (channel: string): SharedConnection => {

View File

@ -71,8 +71,7 @@ export default Vue.extend({
this.pingClock = setInterval(() => { this.pingClock = setInterval(() => {
if (this.matching) { if (this.matching) {
this.connection.send({ this.connection.send('ping', {
type: 'ping',
id: this.matching.id id: this.matching.id
}); });
} }

View File

@ -103,6 +103,12 @@ export default Vue.extend({
(this as any).api('notes/favorites/create', { (this as any).api('notes/favorites/create', {
noteId: this.note.id noteId: this.note.id
}).then(() => { }).then(() => {
this.$swal({
type: 'success',
showConfirmButton: false,
timer: 1250,
customClass: 'swal-icon-only'
});
this.destroyDom(); this.destroyDom();
}); });
}, },

View File

@ -67,22 +67,30 @@
</details> </details>
<details> <details>
<summary>%fa:folder-open% %i18n:@installed-themes%</summary> <summary>%fa:folder-open% %i18n:@manage-themes%</summary>
<ui-select v-model="selectedInstalledThemeId" placeholder="%i18n:@select-theme%"> <ui-select v-model="selectedThemeId" placeholder="%i18n:@select-theme%">
<option v-for="x in installedThemes" :value="x.id" :key="x.id">{{ x.name }}</option> <optgroup label="%i18n:@builtin-themes%">
<option v-for="x in builtinThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
<optgroup label="%i18n:@my-themes%">
<option v-for="x in installedThemes.filter(t => t.author == this.$store.state.i.username)" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
<optgroup label="%i18n:@installed-themes%">
<option v-for="x in installedThemes.filter(t => t.author != this.$store.state.i.username)" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
</ui-select> </ui-select>
<template v-if="selectedInstalledTheme"> <template v-if="selectedTheme">
<ui-input readonly :value="selectedInstalledTheme.author"> <ui-input readonly :value="selectedTheme.author">
<span>%i18n:@author%</span> <span>%i18n:@author%</span>
</ui-input> </ui-input>
<ui-textarea v-if="selectedInstalledTheme.desc" readonly :value="selectedInstalledTheme.desc"> <ui-textarea v-if="selectedTheme.desc" readonly :value="selectedTheme.desc">
<span>%i18n:@desc%</span> <span>%i18n:@desc%</span>
</ui-textarea> </ui-textarea>
<ui-textarea readonly :value="selectedInstalledThemeCode"> <ui-textarea readonly :value="selectedThemeCode">
<span>%i18n:@theme-code%</span> <span>%i18n:@theme-code%</span>
</ui-textarea> </ui-textarea>
<ui-button @click="export_()" link :download="`${selectedInstalledTheme.name}.misskeytheme`" ref="export">%fa:box% %i18n:@export%</ui-button> <ui-button @click="export_()" link :download="`${selectedTheme.name}.misskeytheme`" ref="export">%fa:box% %i18n:@export%</ui-button>
<ui-button @click="uninstall()">%fa:trash-alt R% %i18n:@uninstall%</ui-button> <ui-button @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)">%fa:trash-alt R% %i18n:@uninstall%</ui-button>
</template> </template>
</details> </details>
</div> </div>
@ -117,8 +125,9 @@ export default Vue.extend({
data() { data() {
return { return {
builtinThemes: builtinThemes,
installThemeCode: null, installThemeCode: null,
selectedInstalledThemeId: null, selectedThemeId: null,
myThemeBase: 'light', myThemeBase: 'light',
myThemeName: '', myThemeName: '',
myThemeDesc: '', myThemeDesc: '',
@ -155,14 +164,14 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'darkTheme', value }); } set(value) { this.$store.commit('device/set', { key: 'darkTheme', value }); }
}, },
selectedInstalledTheme() { selectedTheme() {
if (this.selectedInstalledThemeId == null) return null; if (this.selectedThemeId == null) return null;
return this.installedThemes.find(x => x.id == this.selectedInstalledThemeId); return this.themes.find(x => x.id == this.selectedThemeId);
}, },
selectedInstalledThemeCode() { selectedThemeCode() {
if (this.selectedInstalledTheme == null) return null; if (this.selectedTheme == null) return null;
return JSON5.stringify(this.selectedInstalledTheme, null, '\t'); return JSON5.stringify(this.selectedTheme, null, '\t');
}, },
myTheme(): any { myTheme(): any {
@ -238,7 +247,7 @@ export default Vue.extend({
}, },
uninstall() { uninstall() {
const theme = this.selectedInstalledTheme; const theme = this.selectedTheme;
const themes = this.$store.state.device.themes.filter(t => t.id != theme.id); const themes = this.$store.state.device.themes.filter(t => t.id != theme.id);
this.$store.commit('device/set', { this.$store.commit('device/set', {
key: 'themes', value: themes key: 'themes', value: themes
@ -251,7 +260,7 @@ export default Vue.extend({
} }
export_() { export_() {
const blob = new Blob([this.selectedInstalledThemeCode], { const blob = new Blob([this.selectedThemeCode], {
type: 'application/json5' type: 'application/json5'
}); });
this.$refs.export.$el.href = window.URL.createObjectURL(blob); this.$refs.export.$el.href = window.URL.createObjectURL(blob);

View File

@ -113,8 +113,7 @@ export default define({
this.connection.on('stats', this.onStats); this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog); this.connection.on('statsLog', this.onStatsLog);
this.connection.send({ this.connection.send('requestLog',{
type: 'requestLog',
id: Math.random().toString() id: Math.random().toString()
}); });
}, },

View File

@ -91,8 +91,7 @@ export default Vue.extend({
mounted() { mounted() {
this.connection.on('stats', this.onStats); this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog); this.connection.on('statsLog', this.onStatsLog);
this.connection.send({ this.connection.send('requestLog', {
type: 'requestLog',
id: Math.random().toString() id: Math.random().toString()
}); });
}, },

View File

@ -181,8 +181,7 @@ export default Vue.extend({
onNotification(notification) { onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.connection.send({ (this as any).os.stream.send('readNotification', {
type: 'readNotification',
id: notification.id id: notification.id
}); });

View File

@ -77,8 +77,7 @@ export default Vue.extend({
mounted() { mounted() {
this.connection.on('stats', this.onStats); this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog); this.connection.on('statsLog', this.onStatsLog);
this.connection.send({ this.connection.send('requestLog', {
type: 'requestLog',
id: Math.random().toString(), id: Math.random().toString(),
length: 200 length: 200
}); });

View File

@ -113,8 +113,7 @@ export default Vue.extend({
onNotification(notification) { onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.connection.send({ (this as any).os.stream.send('readNotification', {
type: 'readNotification',
id: notification.id id: notification.id
}); });

View File

@ -8,6 +8,7 @@ import VueRouter from 'vue-router';
import * as TreeView from 'vue-json-tree-view'; import * as TreeView from 'vue-json-tree-view';
import VAnimateCss from 'v-animate-css'; import VAnimateCss from 'v-animate-css';
import VModal from 'vue-js-modal'; import VModal from 'vue-js-modal';
import VueSweetalert2 from 'vue-sweetalert2';
import VueHotkey from './common/hotkey'; import VueHotkey from './common/hotkey';
import App from './app.vue'; import App from './app.vue';
@ -26,6 +27,7 @@ Vue.use(TreeView);
Vue.use(VAnimateCss); Vue.use(VAnimateCss);
Vue.use(VModal); Vue.use(VModal);
Vue.use(VueHotkey); Vue.use(VueHotkey);
Vue.use(VueSweetalert2);
// Register global directives // Register global directives
require('./common/views/directives'); require('./common/views/directives');

View File

@ -212,7 +212,7 @@ export default class MiOS extends EventEmitter {
const fetched = () => { const fetched = () => {
this.emit('signedin'); this.emit('signedin');
this.stream = new Stream(this); this.initStream();
// Finish init // Finish init
callback(); callback();
@ -247,12 +247,103 @@ export default class MiOS extends EventEmitter {
// Finish init // Finish init
callback(); callback();
this.stream = new Stream(this); this.initStream();
} }
}); });
} }
} }
@autobind
private initStream() {
this.stream = new Stream(this);
if (this.store.getters.isSignedIn) {
const main = this.stream.useSharedConnection('main');
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
this.store.dispatch('mergeMe', i);
});
main.on('readAllNotifications', () => {
this.store.dispatch('mergeMe', {
hasUnreadNotification: false
});
});
main.on('unreadNotification', () => {
this.store.dispatch('mergeMe', {
hasUnreadNotification: true
});
});
main.on('readAllMessagingMessages', () => {
this.store.dispatch('mergeMe', {
hasUnreadMessagingMessage: false
});
});
main.on('unreadMessagingMessage', () => {
this.store.dispatch('mergeMe', {
hasUnreadMessagingMessage: true
});
});
main.on('unreadMention', () => {
this.store.dispatch('mergeMe', {
hasUnreadMentions: true
});
});
main.on('readAllUnreadMentions', () => {
this.store.dispatch('mergeMe', {
hasUnreadMentions: false
});
});
main.on('unreadSpecifiedNote', () => {
this.store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: true
});
});
main.on('readAllUnreadSpecifiedNotes', () => {
this.store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: false
});
});
main.on('clientSettingUpdated', x => {
this.store.commit('settings/set', {
key: x.key,
value: x.value
});
});
main.on('homeUpdated', x => {
this.store.commit('settings/setHome', x);
});
main.on('mobileHomeUpdated', x => {
this.store.commit('settings/setMobileHome', x);
});
main.on('widgetUpdated', x => {
this.store.commit('settings/setWidget', {
id: x.id,
data: x.data
});
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
alert('%i18n:common.my-token-regenerated%');
this.signout();
});
}
}
/** /**
* Register service worker * Register service worker
*/ */

View File

@ -98,8 +98,7 @@ export default Vue.extend({
onNotification(notification) { onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.connection.send({ (this as any).os.stream.send('readNotification', {
type: 'readNotification',
id: notification.id id: notification.id
}); });

View File

@ -58,8 +58,7 @@ export default Vue.extend({
methods: { methods: {
onNotification(notification) { onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.connection.send({ (this as any).os.stream.send('readNotification', {
type: 'readNotification',
id: notification.id id: notification.id
}); });

View File

@ -17,7 +17,7 @@ const summarize = (note: any): string => {
summary += note.text ? note.text : ''; summary += note.text ? note.text : '';
// ファイルが添付されているとき // ファイルが添付されているとき
if (note.files.length != 0) { if ((note.files || []).length != 0) {
summary += ` (${note.files.length}つのファイル)`; summary += ` (${note.files.length}つのファイル)`;
} }

View File

@ -1,5 +1,6 @@
import * as Minio from 'minio'; import * as Minio from 'minio';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
const sequential = require('promise-sequential');
import DriveFile, { DriveFileChunk, getDriveFileBucket } from '../models/drive-file'; import DriveFile, { DriveFileChunk, getDriveFileBucket } from '../models/drive-file';
import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../models/drive-file-thumbnail'; import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../models/drive-file-thumbnail';
import config from '../config'; import config from '../config';
@ -11,7 +12,7 @@ DriveFile.find({
withoutChunks: false withoutChunks: false
}] }]
}).then(async files => { }).then(async files => {
files.forEach(async file => { await sequential(files.map(file => async () => {
const minio = new Minio.Client(config.drive.config); const minio = new Minio.Client(config.drive.config);
const keyDir = `${config.drive.prefix}/${uuid.v4()}`; const keyDir = `${config.drive.prefix}/${uuid.v4()}`;
@ -60,5 +61,7 @@ DriveFile.find({
await DriveFileThumbnail.remove({ _id: thumbnail._id }); await DriveFileThumbnail.remove({ _id: thumbnail._id });
} }
//#endregion //#endregion
});
console.log('done', file._id);
}));
}); });