Merge branch 'develop'

This commit is contained in:
syuilo 2019-04-17 19:37:32 +09:00
commit 110a2a7121
33 changed files with 93 additions and 92 deletions

View File

@ -56,22 +56,10 @@ jobs:
executor: executor:
type: string type: string
default: "default" default: "default"
without_redis:
type: boolean
default: false
executor: <<parameters.executor>> executor: <<parameters.executor>>
steps: steps:
- attach_workspace: - attach_workspace:
at: /tmp/workspace at: /tmp/workspace
- when:
condition: <<parameters.without_redis>>
steps:
- run:
name: Configure
command: |
mv .config/test.yml .config/test_redis.yml
touch .config/test.yml
cat .config/test_redis.yml | while IFS= read line; do if [[ "$line" = '# __REDIS__' ]]; then break; else echo "$line" >> .config/test.yml; fi; done
- run: - run:
name: Test name: Test
command: | command: |
@ -134,32 +122,14 @@ workflows:
branches: branches:
only: master only: master
- test: - test:
name: manual-test-with-redis name: manual-test
executor: with-redis
requires: requires:
- manual-build - manual-build
filters: filters:
branches: branches:
ignore: master ignore: master
- test: - test:
name: auto-test-without-redis name: auto-test
executor: with-redis
requires:
- auto-build
filters:
branches:
only: master
- test:
name: manual-test-with-redis
without_redis: true
requires:
- manual-build
filters:
branches:
ignore: master
- test:
name: auto-test-without-redis
without_redis: true
requires: requires:
- auto-build - auto-build
filters: filters:

View File

@ -5,6 +5,13 @@ If you encounter any problems with updating, please try the following:
1. `npm run clean` or `npm run cleanall` 1. `npm run clean` or `npm run cleanall`
2. Retry update (Don't forget `npm i`) 2. Retry update (Don't forget `npm i`)
11.1.5 (2019/04/17)
-------------------
### Fixes
* ユーザー名に含まれているカスタム絵文字が表示されないことがある問題を修正
* 壁紙の設定ができない問題を修正
* デザインの調整
11.1.4 (2019/04/17) 11.1.4 (2019/04/17)
------------------- -------------------
### Fixes ### Fixes

View File

@ -46,10 +46,40 @@ Convert な(na) to にゃ(nya)
Revert Nyaize Revert Nyaize
## Code style ## Code style
### Use semicolon ### セミコロンを省略しない
To avoid ASI Hazard ASI Hazardを避けるためでもある
### 中括弧を省略しない
Bad:
``` ts
if (foo)
bar;
else
baz;
```
Good:
``` ts
if (foo) {
bar;
} else {
baz;
}
```
ただし**`if`が一行**の時だけは省略しても良い
Good:
``` ts
if (foo) bar;
```
### `export default`を使わない
インテリセンスと相性が悪かったりするため
参考:
* https://gfx.hatenablog.com/entry/2017/11/24/135343
* https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
### Don't use `export default`
Bad: Bad:
``` ts ``` ts
export default function(foo: string): string { export default function(foo: string): string {

View File

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "11.1.4", "version": "11.1.5",
"codename": "daybreak", "codename": "daybreak",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -137,7 +137,6 @@ export default prop => ({
Vue.set(this.$_ns_target, 'deletedAt', body.deletedAt); Vue.set(this.$_ns_target, 'deletedAt', body.deletedAt);
Vue.set(this.$_ns_target, 'renote', null); Vue.set(this.$_ns_target, 'renote', null);
this.$_ns_target.text = null; this.$_ns_target.text = null;
this.$_ns_target.tags = [];
this.$_ns_target.fileIds = []; this.$_ns_target.fileIds = [];
this.$_ns_target.poll = null; this.$_ns_target.poll = null;
this.$_ns_target.geo = null; this.$_ns_target.geo = null;

View File

@ -121,7 +121,7 @@ export default Vue.extend({
if (this.file.properties.avgColor) { if (this.file.properties.avgColor) {
anime({ anime({
targets: this.$refs.thumbnail, targets: this.$refs.thumbnail,
backgroundColor: this.file.properties.avgColor.replace('255)', '0)'), backgroundColor: 'transparent', // TODO fade
duration: 100, duration: 100,
easing: 'linear' easing: 'linear'
}); });

View File

@ -32,7 +32,7 @@ export default Vue.extend({
props: { props: {
files: { files: {
type: Object, type: Array,
required: true required: true
}, },
detachMediaFn: { detachMediaFn: {

View File

@ -525,15 +525,11 @@ export default Vue.extend({
this.$chooseDriveFile({ this.$chooseDriveFile({
multiple: false multiple: false
}).then(file => { }).then(file => {
this.$root.api('i/update', { this.$store.dispatch('settings/set', { key: 'wallpaper', value: file.url });
wallpaperId: file.id
});
}); });
}, },
deleteWallpaper() { deleteWallpaper() {
this.$root.api('i/update', { this.$store.dispatch('settings/set', { key: 'wallpaper', value: null });
wallpaperId: null
});
}, },
checkForUpdate() { checkForUpdate() {
this.checkingForUpdate = true; this.checkingForUpdate = true;

View File

@ -21,7 +21,7 @@
<fa :icon="['far', 'laugh']"/> <fa :icon="['far', 'laugh']"/>
</button> </button>
</div> </div>
<x-post-form-attaches class="files" :files="files" :detachMediaFn="detachMedia"/> <x-post-form-attaches class="files" :files="files" :detach-media-fn="detachMedia"/>
<input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/> <input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/>
<mk-uploader ref="uploader" @uploaded="attachMedia"/> <mk-uploader ref="uploader" @uploaded="attachMedia"/>
<footer> <footer>

View File

@ -142,7 +142,7 @@ export default Vue.extend({
if (this.file.properties.avgColor) { if (this.file.properties.avgColor) {
anime({ anime({
targets: this.$refs.thumbnail, targets: this.$refs.thumbnail,
backgroundColor: this.file.properties.avgColor.replace('255)', '0)'), backgroundColor: 'transparent', // TODO fade
duration: 100, duration: 100,
easing: 'linear' easing: 'linear'
}); });

View File

@ -87,6 +87,5 @@ export default Vue.extend({
height 100% height 100%
flex auto flex auto
overflow auto overflow auto
background var(--bg)
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="mk-ui" v-hotkey.global="keymap"> <div class="mk-ui" v-hotkey.global="keymap">
<div class="bg" v-if="$store.getters.isSignedIn && $store.state.i.wallpaperUrl" :style="style"></div> <div class="bg" v-if="$store.getters.isSignedIn && $store.state.settings.wallpaper" :style="style"></div>
<x-header class="header" v-if="navbar == 'top'" v-show="!zenMode" ref="header"/> <x-header class="header" v-if="navbar == 'top'" v-show="!zenMode" ref="header"/>
<x-sidebar class="sidebar" v-if="navbar != 'top'" v-show="!zenMode" ref="sidebar"/> <x-sidebar class="sidebar" v-if="navbar != 'top'" v-show="!zenMode" ref="sidebar"/>
<div class="content" :class="[{ sidebar: navbar != 'top', zen: zenMode }, navbar]"> <div class="content" :class="[{ sidebar: navbar != 'top', zen: zenMode }, navbar]">
@ -33,10 +33,9 @@ export default Vue.extend({
}, },
style(): any { style(): any {
if (!this.$store.getters.isSignedIn || this.$store.state.i.wallpaperUrl == null) return {}; if (!this.$store.getters.isSignedIn || this.$store.state.settings.wallpaper == null) return {};
return { return {
backgroundColor: this.$store.state.i.wallpaperColor && this.$store.state.i.wallpaperColor.length == 3 ? `rgb(${ this.$store.state.i.wallpaperColor.join(',') })` : null, backgroundImage: `url(${ this.$store.state.settings.wallpaper })`
backgroundImage: `url(${ this.$store.state.i.wallpaperUrl })`
}; };
}, },
@ -96,7 +95,6 @@ export default Vue.extend({
background-size cover background-size cover
background-position center background-position center
background-attachment fixed background-attachment fixed
opacity 0.3
> .content.sidebar.left > .content.sidebar.left
padding-left 68px padding-left 68px

View File

@ -28,6 +28,7 @@ const defaultSettings = {
iLikeSushi: false, iLikeSushi: false,
rememberNoteVisibility: false, rememberNoteVisibility: false,
defaultNoteVisibility: 'public', defaultNoteVisibility: 'public',
wallpaper: null,
webSearchEngine: 'https://www.google.com/?#q={{query}}', webSearchEngine: 'https://www.google.com/?#q={{query}}',
mutedWords: [], mutedWords: [],
games: { games: {

View File

@ -76,8 +76,6 @@ class MyCustomLogger implements Logger {
} }
export function initDb(justBorrow = false, sync = false, log = false) { export function initDb(justBorrow = false, sync = false, log = false) {
const enableLogging = log || !['production', 'test'].includes(process.env.NODE_ENV || '');
try { try {
const conn = getConnection(); const conn = getConnection();
return Promise.resolve(conn); return Promise.resolve(conn);
@ -92,8 +90,8 @@ export function initDb(justBorrow = false, sync = false, log = false) {
database: config.db.db, database: config.db.db,
synchronize: process.env.NODE_ENV === 'test' || sync, synchronize: process.env.NODE_ENV === 'test' || sync,
dropSchema: process.env.NODE_ENV === 'test' && !justBorrow, dropSchema: process.env.NODE_ENV === 'test' && !justBorrow,
logging: enableLogging, logging: log,
logger: enableLogging ? new MyCustomLogger() : undefined, logger: log ? new MyCustomLogger() : undefined,
entities: [ entities: [
Meta, Meta,
Instance, Instance,

View File

@ -178,12 +178,11 @@ export class NoteRepository extends Repository<Note> {
name: In(reactionEmojis), name: In(reactionEmojis),
host: host host: host
}) : [], }) : [],
tags: note.tags,
fileIds: note.fileIds, fileIds: note.fileIds,
files: DriveFiles.packMany(note.fileIds), files: DriveFiles.packMany(note.fileIds),
replyId: note.replyId, replyId: note.replyId,
renoteId: note.renoteId, renoteId: note.renoteId,
uri: note.uri, uri: note.uri || undefined,
...(opts.detail ? { ...(opts.detail ? {
reply: note.replyId ? this.pack(note.replyId, meId, { reply: note.replyId ? this.pack(note.replyId, meId, {

View File

@ -82,7 +82,7 @@ export class UserRepository extends Repository<User> {
const relation = meId && (meId !== user.id) && opts.detail ? await this.getRelation(meId, user.id) : null; const relation = meId && (meId !== user.id) && opts.detail ? await this.getRelation(meId, user.id) : null;
const pins = opts.detail ? await UserNotePinings.find({ userId: user.id }) : []; const pins = opts.detail ? await UserNotePinings.find({ userId: user.id }) : [];
const profile = opts.detail ? await UserProfiles.findOne({ userId: user.id }).then(ensure) : null; const profile = opts.detail ? await UserProfiles.findOne(user.id).then(ensure) : null;
const falsy = opts.detail ? false : undefined; const falsy = opts.detail ? false : undefined;

View File

@ -17,7 +17,7 @@ export async function renderPerson(user: ILocalUser) {
const [avatar, banner, profile] = await Promise.all([ const [avatar, banner, profile] = await Promise.all([
user.avatarId ? DriveFiles.findOne(user.avatarId) : Promise.resolve(undefined), user.avatarId ? DriveFiles.findOne(user.avatarId) : Promise.resolve(undefined),
user.bannerId ? DriveFiles.findOne(user.bannerId) : Promise.resolve(undefined), user.bannerId ? DriveFiles.findOne(user.bannerId) : Promise.resolve(undefined),
UserProfiles.findOne({ userId: user.id }).then(ensure) UserProfiles.findOne(user.id).then(ensure)
]); ]);
const attachment: { const attachment: {

View File

@ -19,7 +19,7 @@ export const meta = {
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const token = ps.token.replace(/\s/g, ''); const token = ps.token.replace(/\s/g, '');
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
if (profile.twoFactorTempSecret == null) { if (profile.twoFactorTempSecret == null) {
throw new Error('二段階認証の設定が開始されていません'); throw new Error('二段階認証の設定が開始されていません');

View File

@ -20,7 +20,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, profile.password!); const same = await bcrypt.compare(ps.password, profile.password!);

View File

@ -17,7 +17,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, profile.password!); const same = await bcrypt.compare(ps.password, profile.password!);

View File

@ -21,7 +21,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.currentPassword, profile.password!); const same = await bcrypt.compare(ps.currentPassword, profile.password!);

View File

@ -17,7 +17,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, profile.password!); const same = await bcrypt.compare(ps.password, profile.password!);

View File

@ -19,7 +19,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, profile.password!); const same = await bcrypt.compare(ps.password, profile.password!);

View File

@ -33,7 +33,7 @@ export const meta = {
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, profile.password!); const same = await bcrypt.compare(ps.password, profile.password!);

View File

@ -13,6 +13,7 @@ import { ApiError } from '../../error';
import { Users, DriveFiles, UserProfiles } from '../../../../models'; import { Users, DriveFiles, UserProfiles } from '../../../../models';
import { User } from '../../../../models/entities/user'; import { User } from '../../../../models/entities/user';
import { UserProfile } from '../../../../models/entities/user-profile'; import { UserProfile } from '../../../../models/entities/user-profile';
import { ensure } from '../../../../prelude/ensure';
export const meta = { export const meta = {
desc: { desc: {
@ -157,22 +158,24 @@ export default define(meta, async (ps, user, app) => {
const isSecure = user != null && app == null; const isSecure = user != null && app == null;
const updates = {} as Partial<User>; const updates = {} as Partial<User>;
const profile = {} as Partial<UserProfile>; const profileUpdates = {} as Partial<UserProfile>;
const profile = await UserProfiles.findOne(user.id).then(ensure);
if (ps.name !== undefined) updates.name = ps.name; if (ps.name !== undefined) updates.name = ps.name;
if (ps.description !== undefined) profile.description = ps.description; if (ps.description !== undefined) profileUpdates.description = ps.description;
//if (ps.lang !== undefined) updates.lang = ps.lang; //if (ps.lang !== undefined) updates.lang = ps.lang;
if (ps.location !== undefined) profile.location = ps.location; if (ps.location !== undefined) profileUpdates.location = ps.location;
if (ps.birthday !== undefined) profile.birthday = ps.birthday; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
if (typeof ps.isLocked == 'boolean') updates.isLocked = ps.isLocked; if (typeof ps.isLocked == 'boolean') updates.isLocked = ps.isLocked;
if (typeof ps.isBot == 'boolean') updates.isBot = ps.isBot; if (typeof ps.isBot == 'boolean') updates.isBot = ps.isBot;
if (typeof ps.carefulBot == 'boolean') profile.carefulBot = ps.carefulBot; if (typeof ps.carefulBot == 'boolean') profileUpdates.carefulBot = ps.carefulBot;
if (typeof ps.autoAcceptFollowed == 'boolean') profile.autoAcceptFollowed = ps.autoAcceptFollowed; if (typeof ps.autoAcceptFollowed == 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
if (typeof ps.isCat == 'boolean') updates.isCat = ps.isCat; if (typeof ps.isCat == 'boolean') updates.isCat = ps.isCat;
if (typeof ps.autoWatch == 'boolean') profile.autoWatch = ps.autoWatch; if (typeof ps.autoWatch == 'boolean') profileUpdates.autoWatch = ps.autoWatch;
if (typeof ps.alwaysMarkNsfw == 'boolean') profile.alwaysMarkNsfw = ps.alwaysMarkNsfw; if (typeof ps.alwaysMarkNsfw == 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
if (ps.avatarId) { if (ps.avatarId) {
const avatar = await DriveFiles.findOne(ps.avatarId); const avatar = await DriveFiles.findOne(ps.avatarId);
@ -201,16 +204,20 @@ export default define(meta, async (ps, user, app) => {
} }
//#region emojis/tags //#region emojis/tags
let emojis = [] as string[]; let emojis = [] as string[];
let tags = [] as string[]; let tags = [] as string[];
if (updates.name != null) { const newName = updates.name === undefined ? user.name : updates.name;
const tokens = parsePlain(updates.name); const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
if (newName != null) {
const tokens = parsePlain(newName);
emojis = emojis.concat(extractEmojis(tokens!)); emojis = emojis.concat(extractEmojis(tokens!));
} }
if (profile.description != null) { if (newDescription != null) {
const tokens = parse(profile.description); const tokens = parse(newDescription);
emojis = emojis.concat(extractEmojis(tokens!)); emojis = emojis.concat(extractEmojis(tokens!));
tags = extractHashtags(tokens!).map(tag => tag.toLowerCase()); tags = extractHashtags(tokens!).map(tag => tag.toLowerCase());
} }
@ -224,7 +231,7 @@ export default define(meta, async (ps, user, app) => {
//#endregion //#endregion
if (Object.keys(updates).length > 0) await Users.update(user.id, updates); if (Object.keys(updates).length > 0) await Users.update(user.id, updates);
if (Object.keys(profile).length > 0) await UserProfiles.update({ userId: user.id }, profile); if (Object.keys(profileUpdates).length > 0) await UserProfiles.update({ userId: user.id }, profileUpdates);
const iObj = await Users.pack(user.id, user, { const iObj = await Users.pack(user.id, user, {
detail: true, detail: true,

View File

@ -150,7 +150,7 @@ export default define(meta, async (ps, user) => {
} }
}); });
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// この投稿をWatchする // この投稿をWatchする
if (profile.autoWatch !== false) { if (profile.autoWatch !== false) {

View File

@ -1,4 +1,3 @@
export const schemas = { export const schemas = {
Error: { Error: {
type: 'object', type: 'object',

View File

@ -46,7 +46,7 @@ export default async (ctx: Koa.BaseContext) => {
return; return;
} }
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// Compare password // Compare password
const same = await bcrypt.compare(password, profile.password!); const same = await bcrypt.compare(password, profile.password!);

View File

@ -11,7 +11,7 @@ export default async function(user: User) {
name: user.name || user.username name: user.name || user.username
}; };
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
const notes = await Notes.find({ const notes = await Notes.find({
where: { where: {

View File

@ -363,16 +363,14 @@ export default async function(
logger.debug(`average color is calculated: ${r}, ${g}, ${b}`); logger.debug(`average color is calculated: ${r}, ${g}, ${b}`);
const value = info.isOpaque ? `rgba(${r},${g},${b},0)` : `rgba(${r},${g},${b},255)`; properties['avgColor'] = `rgb(${r},${g},${b})`;
properties['avgColor'] = value;
} catch (e) { } } catch (e) { }
}; };
propPromises = [calcWh(), calcAvg()]; propPromises = [calcWh(), calcAvg()];
} }
const profile = await UserProfiles.findOne({ userId: user.id }); const profile = await UserProfiles.findOne(user.id);
const [folder] = await Promise.all([fetchFolder(), Promise.all(propPromises)]); const [folder] = await Promise.all([fetchFolder(), Promise.all(propPromises)]);

View File

@ -253,7 +253,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity); deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity);
} }
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure); const profile = await UserProfiles.findOne(user.id).then(ensure);
// If has in reply to note // If has in reply to note
if (data.reply) { if (data.reply) {

View File

@ -67,7 +67,7 @@ export default async function(user: User, note: Note, choice: number) {
} }
}); });
const profile = await UserProfiles.findOne({ userId: user.id }); const profile = await UserProfiles.findOne(user.id);
// ローカルユーザーが投票した場合この投稿をWatchする // ローカルユーザーが投票した場合この投稿をWatchする
if (Users.isLocalUser(user) && profile!.autoWatch) { if (Users.isLocalUser(user) && profile!.autoWatch) {

View File

@ -80,7 +80,7 @@ export default async (user: User, note: Note, reaction?: string) => {
} }
}); });
const profile = await UserProfiles.findOne({ userId: user.id }); const profile = await UserProfiles.findOne(user.id);
// ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする // ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする
if (Users.isLocalUser(user) && profile!.autoWatch) { if (Users.isLocalUser(user) && profile!.autoWatch) {