Merge branch 'develop' into swn

This commit is contained in:
tamaina 2021-10-14 02:02:38 +09:00
commit b0ecb8013b
16 changed files with 87 additions and 13 deletions

View file

@ -18,7 +18,8 @@
- クライアント: MFM関数構文のサジェストを実装 - クライアント: MFM関数構文のサジェストを実装
- クライアント: 未読の通知のみ表示する機能 - クライアント: 未読の通知のみ表示する機能
- クライアント: 通知ページで通知の種類によるフィルタ - クライアント: 通知ページで通知の種類によるフィルタ
- クライアント: ピン留めユーザーの設定項目がない問題を修正 - クライアント: 新しいダークテーマを追加
- クライアント: テーマコンパイラに hue と saturate 関数を追加
- ActivityPub: HTML -> MFMの変換を強化 - ActivityPub: HTML -> MFMの変換を強化
- API: i/notifications に unreadOnly オプションを追加 - API: i/notifications に unreadOnly オプションを追加
- API: ap系のエンドポイントをログイン必須化+レートリミット追加 - API: ap系のエンドポイントをログイン必須化+レートリミット追加
@ -31,6 +32,8 @@
- クライアント: ヘッダーのタブが折り返される問題を修正 - クライアント: ヘッダーのタブが折り返される問題を修正
- クライアント: ヘッダーにタブが表示されている状態でタイトルをクリックしたときにタブ選択が表示されるのを修正 - クライアント: ヘッダーにタブが表示されている状態でタイトルをクリックしたときにタブ選択が表示されるのを修正
- クライアント: ユーザーページのタブが機能していない問題を修正 - クライアント: ユーザーページのタブが機能していない問題を修正
- クライアント: ピン留めユーザーの設定項目がない問題を修正
- API: 管理者およびモデレーターをブロックできてしまう問題を修正
## 12.91.0 (2021/09/22) ## 12.91.0 (2021/09/22)

View file

@ -56,7 +56,7 @@
</label> </label>
<captcha v-if="meta.enableHcaptcha" class="_formBlock captcha" provider="hcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/> <captcha v-if="meta.enableHcaptcha" class="_formBlock captcha" provider="hcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/>
<captcha v-if="meta.enableRecaptcha" class="_formBlock captcha" provider="recaptcha" ref="recaptcha" v-model="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/> <captcha v-if="meta.enableRecaptcha" class="_formBlock captcha" provider="recaptcha" ref="recaptcha" v-model="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/>
<MkButton class="_formBlock" type="submit" :disabled="shouldDisableSubmitting" primary data-cy-signup-submit>{{ $ts.start }}</MkButton> <MkButton class="_formBlock" type="submit" :disabled="shouldDisableSubmitting" gradate data-cy-signup-submit>{{ $ts.start }}</MkButton>
</template> </template>
</form> </form>
</template> </template>

View file

@ -1,6 +1,6 @@
<template> <template>
<button v-if="!link" class="bghgjjyj _button" <button v-if="!link" class="bghgjjyj _button"
:class="{ inline, primary, danger, rounded, full }" :class="{ inline, primary, gradate, danger, rounded, full }"
:type="type" :type="type"
@click="$emit('click', $event)" @click="$emit('click', $event)"
@mousedown="onMousedown" @mousedown="onMousedown"
@ -11,7 +11,7 @@
</div> </div>
</button> </button>
<MkA v-else class="bghgjjyj _button" <MkA v-else class="bghgjjyj _button"
:class="{ inline, primary, danger, rounded, full }" :class="{ inline, primary, gradate, danger, rounded, full }"
:to="to" :to="to"
@mousedown="onMousedown" @mousedown="onMousedown"
> >
@ -36,6 +36,11 @@ export default defineComponent({
required: false, required: false,
default: false default: false
}, },
gradate: {
type: Boolean,
required: false,
default: false
},
rounded: { rounded: {
type: Boolean, type: Boolean,
required: false, required: false,
@ -137,8 +142,8 @@ export default defineComponent({
padding: 8px 14px; padding: 8px 14px;
text-align: center; text-align: center;
font-weight: normal; font-weight: normal;
font-size: 0.9em; font-size: 0.8em;
line-height: 24px; line-height: 22px;
box-shadow: none; box-shadow: none;
text-decoration: none; text-decoration: none;
background: var(--buttonBg); background: var(--buttonBg);
@ -177,6 +182,20 @@ export default defineComponent({
} }
} }
&.gradate {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
&:not(:disabled):hover {
background: var(--X8);
}
&:not(:disabled):active {
background: var(--X8);
}
}
&.danger { &.danger {
color: #ff2a2a; color: #ff2a2a;

View file

@ -27,7 +27,7 @@
<div class="desc" v-html="meta.description || $ts.headlineMisskey"></div> <div class="desc" v-html="meta.description || $ts.headlineMisskey"></div>
</div> </div>
<div class="action"> <div class="action">
<MkButton @click="signup()" inline primary data-cy-signup style="margin-right: 12px;">{{ $ts.signup }}</MkButton> <MkButton @click="signup()" inline gradate data-cy-signup style="margin-right: 12px;">{{ $ts.signup }}</MkButton>
<MkButton @click="signin()" inline data-cy-signin>{{ $ts.login }}</MkButton> <MkButton @click="signin()" inline data-cy-signin>{{ $ts.login }}</MkButton>
</div> </div>
<div class="status" v-if="onlineUsersCount && stats"> <div class="status" v-if="onlineUsersCount && stats">

View file

@ -12,7 +12,7 @@
<div class="desc" v-html="meta.description || $ts.headlineMisskey"></div> <div class="desc" v-html="meta.description || $ts.headlineMisskey"></div>
</div> </div>
<div class="action"> <div class="action">
<MkButton class="signup" @click="signup()" inline primary>{{ $ts.signup }}</MkButton> <MkButton class="signup" @click="signup()" inline gradate>{{ $ts.signup }}</MkButton>
<MkButton class="signin" @click="signin()" inline>{{ $ts.login }}</MkButton> <MkButton class="signin" @click="signin()" inline>{{ $ts.login }}</MkButton>
</div> </div>
<div class="status" v-if="onlineUsersCount && stats"> <div class="status" v-if="onlineUsersCount && stats">

View file

@ -24,7 +24,7 @@
<div class="desc" v-html="meta.description || $ts.headlineMisskey"></div> <div class="desc" v-html="meta.description || $ts.headlineMisskey"></div>
</div> </div>
<div class="action"> <div class="action">
<MkButton @click="signup()" inline primary>{{ $ts.signup }}</MkButton> <MkButton @click="signup()" inline gradate>{{ $ts.signup }}</MkButton>
<MkButton @click="signin()" inline>{{ $ts.login }}</MkButton> <MkButton @click="signin()" inline>{{ $ts.login }}</MkButton>
</div> </div>
<div class="status" v-if="onlineUsersCount && stats"> <div class="status" v-if="onlineUsersCount && stats">

View file

@ -25,6 +25,7 @@ export const builtinThemes = [
require('@client/themes/d-persimmon.json5'), require('@client/themes/d-persimmon.json5'),
require('@client/themes/d-astro.json5'), require('@client/themes/d-astro.json5'),
require('@client/themes/d-future.json5'), require('@client/themes/d-future.json5'),
require('@client/themes/d-botanical.json5'),
require('@client/themes/d-black.json5'), require('@client/themes/d-black.json5'),
] as Theme[]; ] as Theme[];
@ -91,6 +92,8 @@ function compile(theme: Theme): Record<string, string> {
case 'darken': return color.darken(arg); case 'darken': return color.darken(arg);
case 'lighten': return color.lighten(arg); case 'lighten': return color.lighten(arg);
case 'alpha': return color.setAlpha(arg); case 'alpha': return color.setAlpha(arg);
case 'hue': return color.spin(arg);
case 'saturate': return color.saturate(arg);
} }
} }

View file

@ -57,6 +57,8 @@
cwHoverBg: '#707b97', cwHoverBg: '#707b97',
buttonBg: 'rgba(255, 255, 255, 0.05)', buttonBg: 'rgba(255, 255, 255, 0.05)',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)', buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
buttonGradateA: '@accent',
buttonGradateB: ':hue<20<@accent',
inputBorder: 'rgba(255, 255, 255, 0.1)', inputBorder: 'rgba(255, 255, 255, 0.1)',
inputBorderHover: 'rgba(255, 255, 255, 0.2)', inputBorderHover: 'rgba(255, 255, 255, 0.2)',
listItemHoverBg: 'rgba(255, 255, 255, 0.03)', listItemHoverBg: 'rgba(255, 255, 255, 0.03)',

View file

@ -57,6 +57,8 @@
cwHoverBg: '#bbc4ce', cwHoverBg: '#bbc4ce',
buttonBg: 'rgba(0, 0, 0, 0.05)', buttonBg: 'rgba(0, 0, 0, 0.05)',
buttonHoverBg: 'rgba(0, 0, 0, 0.1)', buttonHoverBg: 'rgba(0, 0, 0, 0.1)',
buttonGradateA: '@accent',
buttonGradateB: ':hue<20<@accent',
inputBorder: 'rgba(0, 0, 0, 0.1)', inputBorder: 'rgba(0, 0, 0, 0.1)',
inputBorderHover: 'rgba(0, 0, 0, 0.2)', inputBorderHover: 'rgba(0, 0, 0, 0.2)',
listItemHoverBg: 'rgba(0, 0, 0, 0.03)', listItemHoverBg: 'rgba(0, 0, 0, 0.03)',

View file

@ -46,6 +46,8 @@
navIndicator: '@accent', navIndicator: '@accent',
accentLighten: ':lighten<10<@accent', accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)', buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
buttonGradateA: '@accent',
buttonGradateB: ':hue<-20<@accent',
driveFolderBg: ':alpha<0.3<@accent', driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg', fgHighlighted: ':lighten<3<@fg',
panelHeaderBg: ':lighten<3<@panel', panelHeaderBg: ':lighten<3<@panel',

View file

@ -0,0 +1,26 @@
{
id: '504debaf-4912-6a4c-5059-1db08a76b737',
name: 'Mi Botanical Dark',
author: 'syuilo',
base: 'dark',
props: {
accent: 'rgb(148, 179, 0)',
bg: 'rgb(37, 38, 36)',
fg: 'rgb(216, 212, 199)',
fgHighlighted: '#fff',
divider: 'rgba(255, 255, 255, 0.14)',
panel: 'rgb(47, 47, 44)',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
header: ':alpha<0.7<@panel',
navBg: '#363636',
renote: '@accent',
mention: 'rgb(212, 153, 76)',
mentionMe: 'rgb(212, 210, 76)',
hashtag: 'rgb(76, 212, 180)',
link: '@accent',
},
}

View file

@ -21,5 +21,7 @@
mentionMe: '@accent', mentionMe: '@accent',
hashtag: '#70c0e8', hashtag: '#70c0e8',
link: '#e88080', link: '#e88080',
buttonGradateA: '@accent',
buttonGradateB: ':saturate<30<:hue<30<@accent',
}, },
} }

View file

@ -372,7 +372,7 @@ export default defineComponent({
right: 0; right: 0;
bottom: 0; bottom: 0;
border-radius: 999px; border-radius: 999px;
background: var(--accent); background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
} }
&:hover, &.active { &:hover, &.active {

View file

@ -4,7 +4,7 @@
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
</button> </button>
<div class="post" @click="post" data-cy-open-post-form> <div class="post" @click="post" data-cy-open-post-form>
<MkButton class="button" primary full> <MkButton class="button" gradate full rounded>
<i class="fas fa-pencil-alt fa-fw"></i><span class="text" v-if="!iconOnly">{{ $ts.note }}</span> <i class="fas fa-pencil-alt fa-fw"></i><span class="text" v-if="!iconOnly">{{ $ts.note }}</span>
</MkButton> </MkButton>
</div> </div>

View file

@ -43,6 +43,12 @@ export const meta = {
code: 'ALREADY_BLOCKING', code: 'ALREADY_BLOCKING',
id: '787fed64-acb9-464a-82eb-afbd745b9614' id: '787fed64-acb9-464a-82eb-afbd745b9614'
}, },
cannotBlockModerator: {
message: 'Cannot block a moderator or an admin.',
code: 'CANNOT_BLOCK_MODERATOR',
id: '8544aaef-89fb-e470-9f6c-385d38b474f5'
}
}, },
res: { res: {
@ -76,8 +82,12 @@ export default define(meta, async (ps, user) => {
throw new ApiError(meta.errors.alreadyBlocking); throw new ApiError(meta.errors.alreadyBlocking);
} }
// Create blocking try {
await create(blocker, blockee); await create(blocker, blockee);
} catch (e) {
if (e.id === 'e42b7890-5e4d-9d9c-d54b-cf4dd30adfb5') throw new ApiError(meta.errors.cannotBlockModerator);
throw e;
}
NoteWatchings.delete({ NoteWatchings.delete({
userId: blocker.id, userId: blocker.id,

View file

@ -9,8 +9,13 @@ import { User } from '@/models/entities/user';
import { Blockings, Users, FollowRequests, Followings, UserListJoinings, UserLists } from '@/models/index'; import { Blockings, Users, FollowRequests, Followings, UserListJoinings, UserLists } from '@/models/index';
import { perUserFollowingChart } from '@/services/chart/index'; import { perUserFollowingChart } from '@/services/chart/index';
import { genId } from '@/misc/gen-id'; import { genId } from '@/misc/gen-id';
import { IdentifiableError } from '@/misc/identifiable-error';
export default async function(blocker: User, blockee: User) { export default async function(blocker: User, blockee: User) {
if (blockee.isAdmin || blockee.isModerator) {
throw new IdentifiableError('e42b7890-5e4d-9d9c-d54b-cf4dd30adfb5');
}
await Promise.all([ await Promise.all([
cancelRequest(blocker, blockee), cancelRequest(blocker, blockee),
cancelRequest(blockee, blocker), cancelRequest(blockee, blocker),