Merge branch 'develop' of https://github.com/ThatOneCalculator/misskey into develop
This commit is contained in:
		
						commit
						a55e27ef88
					
				
					 40 changed files with 320 additions and 303 deletions
				
			
		
							
								
								
									
										19
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								CHANGELOG.md
									
										
									
									
									
								
							|  | @ -9,6 +9,20 @@ | |||
| You should also include the user name that made the change. | ||||
| --> | ||||
| 
 | ||||
| ## 12.112.3 (2022/07/09) | ||||
| 
 | ||||
| ### Improvements | ||||
| - Make active email validation configurable | ||||
| 
 | ||||
| ### Bugfixes | ||||
| - Server: Fix Attempts to update all notifications @mei23 | ||||
| 
 | ||||
| ## 12.112.2 (2022/07/08) | ||||
| 
 | ||||
| ### Bugfixes | ||||
| - Fix Docker doesn't work @mei23   | ||||
|   Still not working on arm64 environment. (See 12.112.0) | ||||
| 
 | ||||
| ## 12.112.1 (2022/07/07) | ||||
| same as 12.112.0 | ||||
| 
 | ||||
|  | @ -21,6 +35,10 @@ same as 12.112.0 | |||
| - ハイライトがみつけるに統合されました | ||||
| - カスタム絵文字ページはインスタンス情報ページに統合されました | ||||
| - 連合ページはインスタンス情報ページに統合されました | ||||
| - メンション一覧ページは通知一覧ページに統合されました | ||||
| - ダイレクト投稿一覧ページは通知一覧ページに統合されました | ||||
| - メニューからアンテナタイムラインを表示する方法は廃止され、タイムライン上部のアイコンからアクセスするようになりました | ||||
| - メニューからリストタイムラインを表示する方法は廃止され、タイムライン上部のアイコンからアクセスするようになりました | ||||
| 
 | ||||
| ### Improvements | ||||
| - Server: Allow GET method for some endpoints @syuilo | ||||
|  | @ -28,6 +46,7 @@ same as 12.112.0 | |||
| - Server: Add rate limit to i/notifications @tamaina | ||||
| - Client: Improve control panel @syuilo | ||||
| - Client: Show warning in control panel when there is an unresolved abuse report @syuilo | ||||
| - Client: Statusbars @syuilo | ||||
| - Client: Add instance-cloud widget @syuilo | ||||
| - Client: Add rss-ticker widget @syuilo | ||||
| - Client: Removing entries from a clip @futchitwo | ||||
|  |  | |||
							
								
								
									
										28
									
								
								Dockerfile
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								Dockerfile
									
										
									
									
									
								
							|  | @ -1,28 +1,24 @@ | |||
| FROM node:18.0.0-alpine3.15 AS base | ||||
| FROM node:16.15.1-bullseye AS builder | ||||
| 
 | ||||
| ARG NODE_ENV=production | ||||
| 
 | ||||
| WORKDIR /misskey | ||||
| 
 | ||||
| ENV BUILD_DEPS autoconf automake file g++ gcc libc-dev libtool make nasm pkgconfig python3 zlib-dev git | ||||
| 
 | ||||
| FROM base AS builder | ||||
| 
 | ||||
| COPY . ./ | ||||
| 
 | ||||
| RUN apk add --no-cache $BUILD_DEPS && \ | ||||
| 	git submodule update --init && \ | ||||
| 	yarn install && \ | ||||
| 	yarn build && \ | ||||
| 	rm -rf .git | ||||
| RUN apt-get update | ||||
| RUN apt-get install -y build-essential | ||||
| RUN git submodule update --init | ||||
| RUN yarn install | ||||
| RUN yarn build | ||||
| RUN rm -rf .git | ||||
| 
 | ||||
| FROM base AS runner | ||||
| FROM node:16.15.1-bullseye-slim AS runner | ||||
| 
 | ||||
| RUN apk add --no-cache \ | ||||
| 	ffmpeg \ | ||||
| 	tini | ||||
| WORKDIR /misskey | ||||
| 
 | ||||
| ENTRYPOINT ["/sbin/tini", "--"] | ||||
| RUN apt-get update | ||||
| RUN apt-get install -y ffmpeg tini | ||||
| 
 | ||||
| COPY --from=builder /misskey/node_modules ./node_modules | ||||
| COPY --from=builder /misskey/built ./built | ||||
|  | @ -32,5 +28,5 @@ COPY --from=builder /misskey/packages/client/node_modules ./packages/client/node | |||
| COPY . ./ | ||||
| 
 | ||||
| ENV NODE_ENV=production | ||||
| ENTRYPOINT ["/usr/bin/tini", "--"] | ||||
| CMD ["npm", "run", "migrateandstart"] | ||||
| 
 | ||||
|  |  | |||
|  | @ -886,6 +886,7 @@ cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためア | |||
| beta: "ベータ" | ||||
| enableAutoSensitive: "自動NSFW判定" | ||||
| enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。" | ||||
| activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。" | ||||
| 
 | ||||
| _sensitiveMediaDetection: | ||||
|   description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。" | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"version": "12.112.1", | ||||
| 	"version": "12.113.0-beta.2", | ||||
| 	"codename": "indigo", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
|  |  | |||
|  | @ -0,0 +1,11 @@ | |||
| export class activeEmailValidation1657346559800 { | ||||
|     name = 'activeEmailValidation1657346559800' | ||||
| 
 | ||||
|     async up(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "enableActiveEmailValidation" boolean NOT NULL DEFAULT true`); | ||||
|     } | ||||
| 
 | ||||
|     async down(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableActiveEmailValidation"`); | ||||
|     } | ||||
| } | ||||
|  | @ -67,7 +67,7 @@ | |||
| 		"koa-send": "5.0.1", | ||||
| 		"koa-slow": "2.1.0", | ||||
| 		"koa-views": "7.0.2", | ||||
| 		"mfm-js": "0.22.1", | ||||
| 		"mfm-js": "0.23.0-canary.1", | ||||
| 		"mime-types": "2.1.35", | ||||
| 		"misskey-js": "0.0.14", | ||||
| 		"mocha": "10.0.0", | ||||
|  | @ -104,7 +104,7 @@ | |||
| 		"strict-event-emitter-types": "2.0.0", | ||||
| 		"stringz": "2.1.0", | ||||
| 		"style-loader": "3.3.1", | ||||
| 		"summaly": "2.6.0", | ||||
| 		"summaly": "2.7.0", | ||||
| 		"syslog-pro": "1.0.0", | ||||
| 		"systeminformation": "5.11.22", | ||||
| 		"tinycolor2": "1.4.2", | ||||
|  |  | |||
|  | @ -7,28 +7,31 @@ import { WriteStream } from 'node:fs'; | |||
| import * as p from 'pureimage'; | ||||
| import gen from 'random-seed'; | ||||
| 
 | ||||
| const size = 256; // px
 | ||||
| const size = 128; // px
 | ||||
| const n = 5; // resolution
 | ||||
| const margin = (size / n); | ||||
| const margin = (size / 4); | ||||
| const colors = [ | ||||
| 	'#e57373', | ||||
| 	'#F06292', | ||||
| 	'#BA68C8', | ||||
| 	'#9575CD', | ||||
| 	'#7986CB', | ||||
| 	'#64B5F6', | ||||
| 	'#4FC3F7', | ||||
| 	'#4DD0E1', | ||||
| 	'#4DB6AC', | ||||
| 	'#81C784', | ||||
| 	'#8BC34A', | ||||
| 	'#AFB42B', | ||||
| 	'#F57F17', | ||||
| 	'#FF5722', | ||||
| 	'#795548', | ||||
| 	'#455A64', | ||||
| 	['#FF512F', '#DD2476'], | ||||
| 	['#FF61D2', '#FE9090'], | ||||
| 	['#72FFB6', '#10D164'], | ||||
| 	['#FD8451', '#FFBD6F'], | ||||
| 	['#305170', '#6DFC6B'], | ||||
| 	['#00C0FF', '#4218B8'], | ||||
| 	['#009245', '#FCEE21'], | ||||
| 	['#0100EC', '#FB36F4'], | ||||
| 	['#FDABDD', '#374A5A'], | ||||
| 	['#38A2D7', '#561139'], | ||||
| 	['#121C84', '#8278DA'], | ||||
| 	['#5761B2', '#1FC5A8'], | ||||
| 	['#FFDB01', '#0E197D'], | ||||
| 	['#FF3E9D', '#0E1F40'], | ||||
| 	['#766eff', '#00d4ff'], | ||||
| 	['#9bff6e', '#00d4ff'], | ||||
| 	['#ff6e94', '#00d4ff'], | ||||
| 	['#ffa96e', '#00d4ff'], | ||||
| 	['#ffa96e', '#ff009d'], | ||||
| 	['#ffdd6e', '#ff009d'], | ||||
| ]; | ||||
| const bg = '#e9e9e9'; | ||||
| 
 | ||||
| const actualSize = size - (margin * 2); | ||||
| const cellSize = actualSize / n; | ||||
|  | @ -42,11 +45,17 @@ export function genIdenticon(seed: string, stream: WriteStream): Promise<void> { | |||
| 	const canvas = p.make(size, size, undefined); | ||||
| 	const ctx = canvas.getContext('2d'); | ||||
| 
 | ||||
| 	const bgColors = colors[rand(colors.length)]; | ||||
| 
 | ||||
| 	const bg = ctx.createLinearGradient(0, 0, size, size); | ||||
| 	bg.addColorStop(0, bgColors[0]); | ||||
| 	bg.addColorStop(1, bgColors[1]); | ||||
| 
 | ||||
| 	ctx.fillStyle = bg; | ||||
| 	ctx.beginPath(); | ||||
| 	ctx.fillRect(0, 0, size, size); | ||||
| 
 | ||||
| 	ctx.fillStyle = colors[rand(colors.length)]; | ||||
| 	ctx.fillStyle = '#ffffff'; | ||||
| 
 | ||||
| 	// side bitmap (filled by false)
 | ||||
| 	const side: boolean[][] = new Array(sideN); | ||||
|  |  | |||
|  | @ -454,4 +454,9 @@ export class Meta { | |||
| 		default: false, | ||||
| 	}) | ||||
| 	public enableIpLogging: boolean; | ||||
| 
 | ||||
| 	@Column('boolean', { | ||||
| 		default: true, | ||||
| 	}) | ||||
| 	public enableActiveEmailValidation: boolean; | ||||
| } | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import { queueLogger } from '../../logger.js'; | |||
| import { addFile } from '@/services/drive/add-file.js'; | ||||
| import { format as dateFormat } from 'date-fns'; | ||||
| import { Users, Emojis } from '@/models/index.js'; | ||||
| import {  } from '@/queue/types.js'; | ||||
| import { } from '@/queue/types.js'; | ||||
| import { createTemp, createTempDir } from '@/misc/create-temp.js'; | ||||
| import { downloadUrl } from '@/misc/download-url.js'; | ||||
| import config from '@/config/index.js'; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import config from '@/config/index.js'; | ||||
| import Resolver from '../resolver.js'; | ||||
| import { IObject, IQuestion, isQuestion  } from '../type.js'; | ||||
| import { IObject, IQuestion, isQuestion } from '../type.js'; | ||||
| import { apLogger } from '../logger.js'; | ||||
| import { Notes, Polls } from '@/models/index.js'; | ||||
| import { IPoll } from '@/models/entities/poll.js'; | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import renderEmoji from './emoji.js'; | |||
| export const renderLike = async (noteReaction: NoteReaction, note: Note) => { | ||||
| 	const reaction = noteReaction.reaction; | ||||
| 
 | ||||
| 	const object =  { | ||||
| 	const object = { | ||||
| 		type: 'Like', | ||||
| 		id: `${config.url}/likes/${noteReaction.id}`, | ||||
| 		actor: `${config.url}/users/${noteReaction.userId}`, | ||||
|  |  | |||
|  | @ -68,11 +68,11 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise<void>((res | |||
| 					} | ||||
| 
 | ||||
| 					try { | ||||
| 						UserIps.insert({ | ||||
| 						UserIps.createQueryBuilder().insert().values({ | ||||
| 							createdAt: new Date(), | ||||
| 							userId: user.id, | ||||
| 							ip: ip, | ||||
| 						}); | ||||
| 						}).orIgnore(true).execute(); | ||||
| 					} catch { | ||||
| 					} | ||||
| 				} | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ export async function readNotificationByQuery( | |||
| 	userId: User['id'], | ||||
| 	query: Record<string, any> | ||||
| ) { | ||||
| 	const notificationIds = await Notifications.find({ | ||||
| 	const notificationIds = await Notifications.findBy({ | ||||
| 		...query, | ||||
| 		notifieeId: userId, | ||||
| 		isRead: false, | ||||
|  |  | |||
|  | @ -324,6 +324,10 @@ export const meta = { | |||
| 				type: 'boolean', | ||||
| 				optional: true, nullable: false, | ||||
| 			}, | ||||
| 			enableActiveEmailValidation: { | ||||
| 				type: 'boolean', | ||||
| 				optional: true, nullable: false, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | @ -421,5 +425,6 @@ export default define(meta, paramDef, async (ps, me) => { | |||
| 		deeplAuthKey: instance.deeplAuthKey, | ||||
| 		deeplIsPro: instance.deeplIsPro, | ||||
| 		enableIpLogging: instance.enableIpLogging, | ||||
| 		enableActiveEmailValidation: instance.enableActiveEmailValidation, | ||||
| 	}; | ||||
| }); | ||||
|  |  | |||
|  | @ -101,6 +101,7 @@ export const paramDef = { | |||
| 		objectStorageSetPublicRead: { type: 'boolean' }, | ||||
| 		objectStorageS3ForcePathStyle: { type: 'boolean' }, | ||||
| 		enableIpLogging: { type: 'boolean' }, | ||||
| 		enableActiveEmailValidation: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
|  | @ -421,6 +422,10 @@ export default define(meta, paramDef, async (ps, me) => { | |||
| 		set.enableIpLogging = ps.enableIpLogging; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ps.enableActiveEmailValidation !== undefined) { | ||||
| 		set.enableActiveEmailValidation = ps.enableActiveEmailValidation; | ||||
| 	} | ||||
| 
 | ||||
| 	await db.transaction(async transactionalEntityManager => { | ||||
| 		const metas = await transactionalEntityManager.find(Meta, { | ||||
| 			order: { | ||||
|  |  | |||
|  | @ -214,7 +214,7 @@ export default define(meta, paramDef, async (ps, _user, token) => { | |||
| 	const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description; | ||||
| 
 | ||||
| 	if (newName != null) { | ||||
| 		const tokens = mfm.parsePlain(newName); | ||||
| 		const tokens = mfm.parseSimple(newName); | ||||
| 		emojis = emojis.concat(extractCustomEmojisFromMfm(tokens!)); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,6 +64,7 @@ export async function pushNotification<T extends keyof pushNotificationsTypes>(u | |||
| 			type, | ||||
| 			body: type === 'notification' ? truncateNotification(body as Packed<'Notification'>) : body, | ||||
| 			userId, | ||||
| 			dateTime: (new Date()).getTime(), | ||||
| 		}), { | ||||
| 			proxy: config.proxy, | ||||
| 		}).catch((err: any) => { | ||||
|  |  | |||
|  | @ -1,34 +1,37 @@ | |||
| import { validate as validateEmail } from 'deep-email-validator'; | ||||
| import { UserProfiles } from '@/models/index.js'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta.js'; | ||||
| 
 | ||||
| export async function validateEmailForAccount(emailAddress: string): Promise<{ | ||||
| 	available: boolean; | ||||
| 	reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp'; | ||||
| }> { | ||||
| 	const meta = await fetchMeta(); | ||||
| 
 | ||||
| 	const exist = await UserProfiles.countBy({ | ||||
| 		emailVerified: true, | ||||
| 		email: emailAddress, | ||||
| 	}); | ||||
| 
 | ||||
| 	const validated = await validateEmail({ | ||||
| 	const validated = meta.enableActiveEmailValidation ? await validateEmail({ | ||||
| 		email: emailAddress, | ||||
| 		validateRegex: true, | ||||
| 		validateMx: true, | ||||
| 		validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
 | ||||
| 		validateDisposable: true, // 捨てアドかどうかチェック
 | ||||
| 		validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
 | ||||
| 	}); | ||||
| 	}) : { valid: true }; | ||||
| 
 | ||||
| 	const available = exist === 0 && validated.valid; | ||||
| 
 | ||||
| 	return { | ||||
| 		available, | ||||
| 		reason: available ? null : | ||||
| 			exist !== 0 ? 'used' : | ||||
| 			validated.reason === 'regex' ? 'format' : | ||||
| 			validated.reason === 'disposable' ? 'disposable' : | ||||
| 			validated.reason === 'mx' ? 'mx' : | ||||
| 			validated.reason === 'smtp' ? 'smtp' : | ||||
| 			null, | ||||
| 		exist !== 0 ? 'used' : | ||||
| 		validated.reason === 'regex' ? 'format' : | ||||
| 		validated.reason === 'disposable' ? 'disposable' : | ||||
| 		validated.reason === 'mx' ? 'mx' : | ||||
| 		validated.reason === 'smtp' ? 'smtp' : | ||||
| 		null, | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 0, | ||||
| 			md5: 'd41d8cd98f00b204e9800998ecf8427e', | ||||
|  | @ -33,6 +34,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 25360, | ||||
| 			md5: '091b3f259662aa31e2ffef4519951168', | ||||
|  | @ -52,6 +54,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 1868, | ||||
| 			md5: '08189c607bea3b952704676bb3c979e0', | ||||
|  | @ -71,6 +74,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 2248, | ||||
| 			md5: '32c47a11555675d9267aee1a86571e7e', | ||||
|  | @ -90,6 +94,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 3772, | ||||
| 			md5: 'f73535c3e1e27508885b69b10cf6e991', | ||||
|  | @ -109,6 +114,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 505, | ||||
| 			md5: 'b6f52b4b021e7b92cdd04509c7267965', | ||||
|  | @ -129,6 +135,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 544, | ||||
| 			md5: '4b7a346cde9ccbeb267e812567e33397', | ||||
|  | @ -148,6 +155,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 75933, | ||||
| 			md5: '268c5dde99e17cf8fe09f1ab3f97df56', | ||||
|  | @ -167,6 +175,7 @@ describe('Get file info', () => { | |||
| 		delete info.warnings; | ||||
| 		delete info.blurhash; | ||||
| 		delete info.sensitive; | ||||
| 		delete info.porn; | ||||
| 		assert.deepStrictEqual(info, { | ||||
| 			size: 12624, | ||||
| 			md5: '68d5b2d8d1d1acbbce99203e3ec3857e', | ||||
|  |  | |||
|  | @ -303,12 +303,7 @@ | |||
|     pluralize "^8.0.0" | ||||
|     yaml-ast-parser "0.0.43" | ||||
| 
 | ||||
| "@sindresorhus/is@^3.0.0": | ||||
|   version "3.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8" | ||||
|   integrity sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ== | ||||
| 
 | ||||
| "@sindresorhus/is@^4.6.0": | ||||
| "@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0": | ||||
|   version "4.6.0" | ||||
|   resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" | ||||
|   integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== | ||||
|  | @ -1736,19 +1731,6 @@ cacheable-lookup@^5.0.3: | |||
|   resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3" | ||||
|   integrity sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w== | ||||
| 
 | ||||
| cacheable-request@^7.0.1: | ||||
|   version "7.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" | ||||
|   integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== | ||||
|   dependencies: | ||||
|     clone-response "^1.0.2" | ||||
|     get-stream "^5.1.0" | ||||
|     http-cache-semantics "^4.0.0" | ||||
|     keyv "^4.0.0" | ||||
|     lowercase-keys "^2.0.0" | ||||
|     normalize-url "^4.1.0" | ||||
|     responselike "^2.0.0" | ||||
| 
 | ||||
| cacheable-request@^7.0.2: | ||||
|   version "7.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" | ||||
|  | @ -3520,19 +3502,19 @@ google-protobuf@^3.9.2: | |||
|   resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.20.1.tgz#1b255c2b59bcda7c399df46c65206aa3c7a0ce8b" | ||||
|   integrity sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw== | ||||
| 
 | ||||
| got@11.5.1: | ||||
|   version "11.5.1" | ||||
|   resolved "https://registry.yarnpkg.com/got/-/got-11.5.1.tgz#bf098a270fe80b3fb88ffd5a043a59ebb0a391db" | ||||
|   integrity sha512-reQEZcEBMTGnujmQ+Wm97mJs/OK6INtO6HmLI+xt3+9CvnRwWjXutUvb2mqr+Ao4Lu05Rx6+udx9sOQAmExMxA== | ||||
| got@11.8.5: | ||||
|   version "11.8.5" | ||||
|   resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" | ||||
|   integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== | ||||
|   dependencies: | ||||
|     "@sindresorhus/is" "^3.0.0" | ||||
|     "@sindresorhus/is" "^4.0.0" | ||||
|     "@szmarczak/http-timer" "^4.0.5" | ||||
|     "@types/cacheable-request" "^6.0.1" | ||||
|     "@types/responselike" "^1.0.0" | ||||
|     cacheable-lookup "^5.0.3" | ||||
|     cacheable-request "^7.0.1" | ||||
|     cacheable-request "^7.0.2" | ||||
|     decompress-response "^6.0.0" | ||||
|     http2-wrapper "^1.0.0-beta.5.0" | ||||
|     http2-wrapper "^1.0.0-beta.5.2" | ||||
|     lowercase-keys "^2.0.0" | ||||
|     p-cancelable "^2.0.0" | ||||
|     responselike "^2.0.0" | ||||
|  | @ -3734,7 +3716,7 @@ http-signature@~1.2.0: | |||
|     jsprim "^1.2.2" | ||||
|     sshpk "^1.7.0" | ||||
| 
 | ||||
| http2-wrapper@^1.0.0-beta.5.0: | ||||
| http2-wrapper@^1.0.0-beta.5.2: | ||||
|   version "1.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" | ||||
|   integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== | ||||
|  | @ -4874,12 +4856,12 @@ methods@^1.1.2: | |||
|   resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" | ||||
|   integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= | ||||
| 
 | ||||
| mfm-js@0.22.1: | ||||
|   version "0.22.1" | ||||
|   resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.22.1.tgz#ad5f0b95cc903ca5a5e414e2edf64ac4648dc8c2" | ||||
|   integrity sha512-UV5zvDKlWPpBFeABhyCzuOTJ3RwrNrmVpJ+zz/dFX6D/ntEywljgxkfsLamcy0ZSwUAr0O+WQxGHvAwyxUgsAQ== | ||||
| mfm-js@0.23.0-canary.1: | ||||
|   version "0.23.0-canary.1" | ||||
|   resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.23.0-canary.1.tgz#1b7b7635f18bed9776054406b72e6bd613c8d0eb" | ||||
|   integrity sha512-SkMrW1rQAv+mFGtLKN9DSv6vxSREDu8ChmkBl1Ch5sQfp47BhuvcRg5EKGmt3WAQRAOylXYMg8wVYR7C5BHKeA== | ||||
|   dependencies: | ||||
|     twemoji-parser "14.0.x" | ||||
|     twemoji-parser "14.0.0" | ||||
| 
 | ||||
| micromatch@^4.0.0, micromatch@^4.0.2: | ||||
|   version "4.0.2" | ||||
|  | @ -5380,11 +5362,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: | |||
|   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" | ||||
|   integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== | ||||
| 
 | ||||
| normalize-url@^4.1.0: | ||||
|   version "4.5.1" | ||||
|   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" | ||||
|   integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== | ||||
| 
 | ||||
| normalize-url@^6.0.1: | ||||
|   version "6.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" | ||||
|  | @ -6974,15 +6951,15 @@ style-loader@3.3.1: | |||
|   resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" | ||||
|   integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== | ||||
| 
 | ||||
| summaly@2.6.0: | ||||
|   version "2.6.0" | ||||
|   resolved "https://registry.yarnpkg.com/summaly/-/summaly-2.6.0.tgz#aaac80eb8ae88b130318f44d9b98da9c2ccb328c" | ||||
|   integrity sha512-wIv6fL3aeFfXcQoZISzeUfNUgD3u8Hwx8Rg0awZliQhans62w23K3nDezwfvmYAQCgXs6e0EF7jtGmJv/qeVTA== | ||||
| summaly@2.7.0: | ||||
|   version "2.7.0" | ||||
|   resolved "https://registry.yarnpkg.com/summaly/-/summaly-2.7.0.tgz#ccccec0477938edea13cb34412a33e705398c0c4" | ||||
|   integrity sha512-pEz9LL8Gp0oPIQfn6TrnBCcv/HkFE14hxhH3W6LPGdopXlPXjRcMlDMJaO+VupUNMOGaMjCsjq7+0rWnu8sp7w== | ||||
|   dependencies: | ||||
|     cheerio "0.22.0" | ||||
|     debug "4.3.3" | ||||
|     escape-regexp "0.0.1" | ||||
|     got "11.5.1" | ||||
|     got "11.8.5" | ||||
|     html-entities "2.3.2" | ||||
|     iconv-lite "0.6.3" | ||||
|     jschardet "3.0.0" | ||||
|  | @ -7310,7 +7287,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: | |||
|   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" | ||||
|   integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= | ||||
| 
 | ||||
| twemoji-parser@14.0.0, twemoji-parser@14.0.x: | ||||
| twemoji-parser@14.0.0: | ||||
|   version "14.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62" | ||||
|   integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA== | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ | |||
| 		"json5": "2.2.1", | ||||
| 		"katex": "0.15.6", | ||||
| 		"matter-js": "0.18.0", | ||||
| 		"mfm-js": "0.22.1", | ||||
| 		"mfm-js": "0.23.0-canary.1", | ||||
| 		"misskey-js": "0.0.14", | ||||
| 		"mocha": "10.0.0", | ||||
| 		"ms": "2.1.3", | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import {  } from 'vue'; | ||||
| import { } from 'vue'; | ||||
| import * as Misskey from 'misskey-js'; | ||||
| import XDrive from './drive.vue'; | ||||
| import XWindow from '@/components/ui/window.vue'; | ||||
|  |  | |||
|  | @ -1,15 +1,15 @@ | |||
| <template> | ||||
| <MkA v-if="url.startsWith('/')" v-user-preview="canonical" :class="[$style.root, { isMe }]" :to="url" :style="{ background: bgCss }"> | ||||
| 	<img :class="$style.icon" :src="`/avatar/@${username}@${host}`" alt=""> | ||||
| <MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="akbvjaqn" :class="{ isMe }" :to="url" :style="{ background: bgCss }"> | ||||
| 	<img class="icon" :src="`/avatar/@${username}@${host}`" alt=""> | ||||
| 	<span class="main"> | ||||
| 		<span class="username">@{{ username }}</span> | ||||
| 		<span v-if="(host != localHost) || $store.state.showFullAcct" :class="$style.mainHost">@{{ toUnicode(host) }}</span> | ||||
| 		<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span> | ||||
| 	</span> | ||||
| </MkA> | ||||
| <a v-else :class="$style.root" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }"> | ||||
| <a v-else class="akbvjaqn" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }"> | ||||
| 	<span class="main"> | ||||
| 		<span class="username">@{{ username }}</span> | ||||
| 		<span :class="$style.mainHost">@{{ toUnicode(host) }}</span> | ||||
| 		<span class="host">@{{ toUnicode(host) }}</span> | ||||
| 	</span> | ||||
| </a> | ||||
| </template> | ||||
|  | @ -41,8 +41,8 @@ const bgCss = bg.toRgbString(); | |||
| useCssModule(); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" module> | ||||
| .root { | ||||
| <style lang="scss" scoped> | ||||
| .akbvjaqn { | ||||
| 	display: inline-block; | ||||
| 	padding: 4px 8px 4px 4px; | ||||
| 	border-radius: 999px; | ||||
|  | @ -51,18 +51,19 @@ useCssModule(); | |||
| 	&.isMe { | ||||
| 		color: var(--mentionMe); | ||||
| 	} | ||||
| 
 | ||||
| 	> .icon { | ||||
| 		width: 1.5em; | ||||
| 		height: 1.5em; | ||||
| 		object-fit: cover; | ||||
| 		margin: 0 0.2em 0 0; | ||||
| 		vertical-align: bottom; | ||||
| 		border-radius: 100%; | ||||
| 	} | ||||
| 
 | ||||
| 	> .host { | ||||
| 		opacity: 0.5; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .icon { | ||||
| 	width: 1.5em; | ||||
| 	height: 1.5em; | ||||
| 	object-fit: cover; | ||||
| 	margin: 0 0.2em 0 0; | ||||
| 	vertical-align: bottom; | ||||
| 	border-radius: 100%; | ||||
| } | ||||
| 
 | ||||
| .mainHost { | ||||
| 	opacity: 0.5; | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ export default defineComponent({ | |||
| 	render() { | ||||
| 		if (this.text == null || this.text === '') return; | ||||
| 
 | ||||
| 		const ast = (this.plain ? mfm.parsePlain : mfm.parse)(this.text, { fnNameList: MFM_TAGS }); | ||||
| 		const ast = (this.plain ? mfm.parseSimple : mfm.parse)(this.text, { fnNameList: MFM_TAGS }); | ||||
| 
 | ||||
| 		const validTime = (t: string | null | undefined) => { | ||||
| 			if (t == null) return null; | ||||
|  |  | |||
|  | @ -105,7 +105,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void { | |||
| 		} | ||||
| 
 | ||||
| 		&.active { | ||||
| 			color: #fff; | ||||
| 			color: var(--fgOnAccent); | ||||
| 			background: var(--accent); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<header> | ||||
| 			<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)" class="mk-widget-select"> | ||||
| 				<template #label>{{ $ts.selectWidget }}</template> | ||||
| 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ $t(`_widgets.${widget}`) }}</option> | ||||
| 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.t(`_widgets.${widget}`) }}</option> | ||||
| 			</MkSelect> | ||||
| 			<MkButton inline primary class="mk-widget-add" @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton> | ||||
|  | @ -26,79 +26,91 @@ | |||
| 			</template> | ||||
| 		</XDraggable> | ||||
| 	</template> | ||||
| 	<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)"/> | ||||
| 	<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent, reactive, ref, computed } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { defineAsyncComponent, reactive, ref, computed } from 'vue'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import MkSelect from '@/components/form/select.vue'; | ||||
| import MkButton from '@/components/ui/button.vue'; | ||||
| import { widgets as widgetDefs } from '@/widgets'; | ||||
| import * as os from '@/os'; | ||||
| import { i18n } from '@/i18n'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XDraggable: defineAsyncComponent(() => import('vuedraggable')), | ||||
| 		MkSelect, | ||||
| 		MkButton, | ||||
| 	}, | ||||
| const XDraggable = defineAsyncComponent(() => import('vuedraggable')); | ||||
| 
 | ||||
| 	props: { | ||||
| 		widgets: { | ||||
| 			type: Array, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		edit: { | ||||
| 			type: Boolean, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 	}, | ||||
| type Widget = { | ||||
| 	name: string; | ||||
| 	id: string; | ||||
| 	data: Record<string, any>; | ||||
| }; | ||||
| 
 | ||||
| 	emits: ['updateWidgets', 'addWidget', 'removeWidget', 'updateWidget', 'exit'], | ||||
| const props = defineProps<{ | ||||
| 	widgets: Widget[]; | ||||
| 	edit: boolean; | ||||
| }>(); | ||||
| 
 | ||||
| 	setup(props, context) { | ||||
| 		const widgetRefs = reactive({}); | ||||
| 		const configWidget = (id: string) => { | ||||
| 			widgetRefs[id].configure(); | ||||
| 		}; | ||||
| 		const widgetAdderSelected = ref(null); | ||||
| 		const addWidget = () => { | ||||
| 			if (widgetAdderSelected.value == null) return; | ||||
| const emit = defineEmits<{ | ||||
| 	(ev: 'updateWidgets', widgets: Widget[]): void; | ||||
| 	(ev: 'addWidget', widget: Widget): void; | ||||
| 	(ev: 'removeWidget', widget: Widget): void; | ||||
| 	(ev: 'updateWidget', widget: Partial<Widget>): void; | ||||
| 	(ev: 'exit'): void; | ||||
| }>(); | ||||
| 
 | ||||
| 			context.emit('addWidget', { | ||||
| 				name: widgetAdderSelected.value, | ||||
| 				id: uuid(), | ||||
| 				data: {}, | ||||
| 			}); | ||||
| const widgetRefs = {}; | ||||
| const configWidget = (id: string) => { | ||||
| 	widgetRefs[id].configure(); | ||||
| }; | ||||
| const widgetAdderSelected = ref(null); | ||||
| const addWidget = () => { | ||||
| 	if (widgetAdderSelected.value == null) return; | ||||
| 
 | ||||
| 			widgetAdderSelected.value = null; | ||||
| 		}; | ||||
| 		const removeWidget = (widget) => { | ||||
| 			context.emit('removeWidget', widget); | ||||
| 		}; | ||||
| 		const updateWidget = (id, data) => { | ||||
| 			context.emit('updateWidget', { id, data }); | ||||
| 		}; | ||||
| 		const widgets_ = computed({ | ||||
| 			get: () => props.widgets, | ||||
| 			set: (value) => { | ||||
| 				context.emit('updateWidgets', value); | ||||
| 			}, | ||||
| 		}); | ||||
| 	emit('addWidget', { | ||||
| 		name: widgetAdderSelected.value, | ||||
| 		id: uuid(), | ||||
| 		data: {}, | ||||
| 	}); | ||||
| 
 | ||||
| 		return { | ||||
| 			widgetRefs, | ||||
| 			configWidget, | ||||
| 			widgetAdderSelected, | ||||
| 			widgetDefs, | ||||
| 			addWidget, | ||||
| 			removeWidget, | ||||
| 			updateWidget, | ||||
| 			widgets_, | ||||
| 		}; | ||||
| 	widgetAdderSelected.value = null; | ||||
| }; | ||||
| const removeWidget = (widget) => { | ||||
| 	emit('removeWidget', widget); | ||||
| }; | ||||
| const updateWidget = (id, data) => { | ||||
| 	emit('updateWidget', { id, data }); | ||||
| }; | ||||
| const widgets_ = computed({ | ||||
| 	get: () => props.widgets, | ||||
| 	set: (value) => { | ||||
| 		emit('updateWidgets', value); | ||||
| 	}, | ||||
| }); | ||||
| 
 | ||||
| function onContextmenu(widget: Widget, ev: MouseEvent) { | ||||
| 	const isLink = (el: HTMLElement) => { | ||||
| 		if (el.tagName === 'A') return true; | ||||
| 		if (el.parentElement) { | ||||
| 			return isLink(el.parentElement); | ||||
| 		} | ||||
| 	}; | ||||
| 	if (isLink(ev.target)) return; | ||||
| 	if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; | ||||
| 	if (window.getSelection()?.toString() !== '') return; | ||||
| 
 | ||||
| 	os.contextMenu([{ | ||||
| 		type: 'label', | ||||
| 		text: i18n.t(`_widgets.${widget.name}`), | ||||
| 	}, { | ||||
| 		icon: 'fas fa-cog', | ||||
| 		text: i18n.ts.settings, | ||||
| 		action: () => { | ||||
| 			configWidget(widget.id); | ||||
| 		}, | ||||
| 	}], ev); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
|  |  | |||
|  | @ -27,8 +27,8 @@ function getClassOrder(width: number, queue: Value): ClassOrder { | |||
| 			...(queue.min ? queue.min.filter(v => width >= v).map(getMinClass) : []), | ||||
| 		], | ||||
| 		remove: [ | ||||
| 			...(queue.max ? queue.max.filter(v => width  > v).map(getMaxClass) : []), | ||||
| 			...(queue.min ? queue.min.filter(v => width  < v).map(getMinClass) : []), | ||||
| 			...(queue.max ? queue.max.filter(v => width > v).map(getMaxClass) : []), | ||||
| 			...(queue.min ? queue.min.filter(v => width < v).map(getMinClass) : []), | ||||
| 		] | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -57,6 +57,19 @@ | |||
| 					</div> | ||||
| 				</FormFolder> | ||||
| 
 | ||||
| 				<FormFolder class="_formBlock"> | ||||
| 					<template #label>Active Email Validation</template> | ||||
| 					<template v-if="enableActiveEmailValidation" #suffix>Enabled</template> | ||||
| 					<template v-else #suffix>Disabled</template> | ||||
| 
 | ||||
| 					<div class="_formRoot"> | ||||
| 						<span class="_formBlock">{{ i18n.ts.activeEmailValidationDescription }}</span> | ||||
| 						<FormSwitch v-model="enableActiveEmailValidation" class="_formBlock" @update:modelValue="save"> | ||||
| 							<template #label>Enable</template> | ||||
| 						</FormSwitch> | ||||
| 					</div> | ||||
| 				</FormFolder> | ||||
| 
 | ||||
| 				<FormFolder class="_formBlock"> | ||||
| 					<template #label>Log IP address</template> | ||||
| 					<template v-if="enableIpLogging" #suffix>Enabled</template> | ||||
|  | @ -112,6 +125,7 @@ let sensitiveMediaDetectionSensitivity: number = $ref(0); | |||
| let setSensitiveFlagAutomatically: boolean = $ref(false); | ||||
| let enableSensitiveMediaDetectionForVideos: boolean = $ref(false); | ||||
| let enableIpLogging: boolean = $ref(false); | ||||
| let enableActiveEmailValidation: boolean = $ref(false); | ||||
| 
 | ||||
| async function init() { | ||||
| 	const meta = await os.api('admin/meta'); | ||||
|  | @ -128,6 +142,7 @@ async function init() { | |||
| 	setSensitiveFlagAutomatically = meta.setSensitiveFlagAutomatically; | ||||
| 	enableSensitiveMediaDetectionForVideos = meta.enableSensitiveMediaDetectionForVideos; | ||||
| 	enableIpLogging = meta.enableIpLogging; | ||||
| 	enableActiveEmailValidation = meta.enableActiveEmailValidation; | ||||
| } | ||||
| 
 | ||||
| function save() { | ||||
|  | @ -144,6 +159,7 @@ function save() { | |||
| 		setSensitiveFlagAutomatically, | ||||
| 		enableSensitiveMediaDetectionForVideos, | ||||
| 		enableIpLogging, | ||||
| 		enableActiveEmailValidation, | ||||
| 	}).then(() => { | ||||
| 		fetchInstance(); | ||||
| 	}); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ export type TextValue = ExprBase & { | |||
| 	value: string; | ||||
| }; | ||||
| 
 | ||||
| export type MultiLineTextValue = ExprBase  & { | ||||
| export type MultiLineTextValue = ExprBase & { | ||||
| 	type: 'multiLineText'; | ||||
| 	value: string; | ||||
| }; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { ref } from 'vue'; | ||||
| import { globalEvents } from '@/events'; | ||||
| import tinycolor from 'tinycolor2'; | ||||
| import { globalEvents } from '@/events'; | ||||
| 
 | ||||
| export type Theme = { | ||||
| 	id: string; | ||||
|  | @ -31,11 +31,11 @@ export const getBuiltinThemes = () => Promise.all( | |||
| 		'd-astro', | ||||
| 		'd-future', | ||||
| 		'd-botanical', | ||||
| 		'd-lime-green', | ||||
| 		'd-orange-green', | ||||
| 		'd-cherry', | ||||
| 		'd-ice', | ||||
| 		'd-pumpkin', | ||||
| 		'd-black', | ||||
| 	].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default)) | ||||
| 	].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default)), | ||||
| ); | ||||
| 
 | ||||
| export const getBuiltinThemesRef = () => { | ||||
|  |  | |||
|  | @ -1,17 +0,0 @@ | |||
| { | ||||
| 	id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1', | ||||
| 
 | ||||
| 	name: 'Mi Black', | ||||
| 	author: 'syuilo', | ||||
| 
 | ||||
| 	base: 'dark', | ||||
| 
 | ||||
| 	props: { | ||||
| 		divider: '#2d2d2d', | ||||
| 		panel: '#131313', | ||||
| 		panelHeaderBg: '@panel', | ||||
| 		panelHeaderDivider: '@divider', | ||||
| 		shadow: 'rgba(255, 255, 255, 0.05)', | ||||
| 		modalBg: 'rgba(255, 255, 255, 0.1)', | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										24
									
								
								packages/client/src/themes/d-lime-green.json5
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								packages/client/src/themes/d-lime-green.json5
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
| 	id: '02816013-8107-440f-877e-865083ffe194', | ||||
| 
 | ||||
| 	name: 'Mi Lime+Green Dark', | ||||
| 	author: 'syuilo', | ||||
| 
 | ||||
| 	base: 'dark', | ||||
| 
 | ||||
| 	props: { | ||||
| 		accent: '#b4e900', | ||||
| 		bg: '#0C1210', | ||||
| 		fg: '#dee7e4', | ||||
| 		fgHighlighted: '#fff', | ||||
| 		fgOnAccent: '#192320', | ||||
| 		divider: '#e7fffb24', | ||||
| 		panel: '#192320', | ||||
| 		panelHeaderBg: '@panel', | ||||
| 		panelHeaderDivider: '@divider', | ||||
| 		popup: '#293330', | ||||
| 		renote: '@accent', | ||||
| 		mentionMe: '#ffaa00', | ||||
| 		link: '#2bceff', | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										24
									
								
								packages/client/src/themes/d-orange-green.json5
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								packages/client/src/themes/d-orange-green.json5
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
| 	id: 'dc489603-27b5-424a-9b25-1ff6aec9824a', | ||||
| 
 | ||||
| 	name: 'Mi Orange+Green Dark', | ||||
| 	author: 'syuilo', | ||||
| 
 | ||||
| 	base: 'dark', | ||||
| 
 | ||||
| 	props: { | ||||
| 		accent: '#e97f00', | ||||
| 		bg: '#0C1210', | ||||
| 		fg: '#dee7e4', | ||||
| 		fgHighlighted: '#fff', | ||||
| 		fgOnAccent: '#192320', | ||||
| 		divider: '#e7fffb24', | ||||
| 		panel: '#192320', | ||||
| 		panelHeaderBg: '@panel', | ||||
| 		panelHeaderDivider: '@divider', | ||||
| 		popup: '#293330', | ||||
| 		renote: '@accent', | ||||
| 		mentionMe: '#ffaa00', | ||||
| 		link: '#2bceff', | ||||
| 	}, | ||||
| } | ||||
|  | @ -1,88 +0,0 @@ | |||
| { | ||||
| 	id: '0b64fef3-02c7-20b5-dd87-b3f77e2b4301', | ||||
| 
 | ||||
| 	name: 'Mi Pumpkin Dark', | ||||
| 	author: 'syuilo', | ||||
| 
 | ||||
| 	base: 'dark', | ||||
| 
 | ||||
| 	props: { | ||||
| 		X2: ':darken<2<@panel', | ||||
| 		X3: 'rgba(255, 255, 255, 0.05)', | ||||
| 		X4: 'rgba(255, 255, 255, 0.1)', | ||||
| 		X5: 'rgba(255, 255, 255, 0.05)', | ||||
| 		X6: 'rgba(255, 255, 255, 0.15)', | ||||
| 		X7: 'rgba(255, 255, 255, 0.05)', | ||||
| 		X8: ':lighten<5<@accent', | ||||
| 		X9: ':darken<5<@accent', | ||||
| 		bg: 'rgb(37, 32, 47)', | ||||
| 		fg: '#e0d5c0', | ||||
| 		X10: ':alpha<0.4<@accent', | ||||
| 		X11: 'rgba(0, 0, 0, 0.3)', | ||||
| 		X12: 'rgba(255, 255, 255, 0.1)', | ||||
| 		X13: 'rgba(255, 255, 255, 0.15)', | ||||
| 		X14: ':alpha<0.5<@navBg', | ||||
| 		X15: ':alpha<0<@panel', | ||||
| 		X16: ':alpha<0.7<@panel', | ||||
| 		X17: ':alpha<0.8<@bg', | ||||
| 		cwBg: '#687390', | ||||
| 		cwFg: '#393f4f', | ||||
| 		link: 'rgb(172, 193, 68)', | ||||
| 		warn: '#ecb637', | ||||
| 		badge: '#31b1ce', | ||||
| 		error: '#ec4137', | ||||
| 		focus: ':alpha<0.3<@accent', | ||||
| 		navBg: '@panel', | ||||
| 		navFg: '@fg', | ||||
| 		panel: ':lighten<3<@bg', | ||||
| 		popup: ':lighten<3<@panel', | ||||
| 		accent: 'rgb(242, 133, 36)', | ||||
| 		header: ':alpha<0.7<@panel', | ||||
| 		infoBg: '#253142', | ||||
| 		infoFg: '#fff', | ||||
| 		renote: 'rgb(110, 179, 72)', | ||||
| 		shadow: 'rgba(0, 0, 0, 0.3)', | ||||
| 		divider: 'rgba(255, 255, 255, 0.1)', | ||||
| 		hashtag: 'rgb(188, 90, 255)', | ||||
| 		mention: 'rgb(72, 179, 139)', | ||||
| 		modalBg: 'rgba(0, 0, 0, 0.5)', | ||||
| 		success: '#86b300', | ||||
| 		buttonBg: 'rgba(255, 255, 255, 0.05)', | ||||
| 		switchBg: 'rgba(255, 255, 255, 0.15)', | ||||
| 		acrylicBg: ':alpha<0.5<@bg', | ||||
| 		cwHoverBg: '#707b97', | ||||
| 		indicator: '@accent', | ||||
| 		mentionMe: '@accent', | ||||
| 		messageBg: '@bg', | ||||
| 		navActive: '@accent', | ||||
| 		accentedBg: ':alpha<0.15<@accent', | ||||
| 		fgOnAccent: '#000', | ||||
| 		infoWarnBg: '#42321c', | ||||
| 		infoWarnFg: '#ffbd3e', | ||||
| 		navHoverFg: ':lighten<17<@fg', | ||||
| 		dateLabelFg: '@fg', | ||||
| 		inputBorder: 'rgba(255, 255, 255, 0.1)', | ||||
| 		panelBorder: '" solid 1px var(--divider)', | ||||
| 		accentDarken: ':darken<10<@accent', | ||||
| 		acrylicPanel: ':alpha<0.5<@panel', | ||||
| 		navIndicator: '@indicator', | ||||
| 		accentLighten: ':lighten<10<@accent', | ||||
| 		buttonHoverBg: 'rgba(255, 255, 255, 0.1)', | ||||
| 		driveFolderBg: ':alpha<0.3<@accent', | ||||
| 		fgHighlighted: ':lighten<3<@fg', | ||||
| 		fgTransparent: ':alpha<0.5<@fg', | ||||
| 		panelHeaderBg: ':lighten<3<@panel', | ||||
| 		panelHeaderFg: '@fg', | ||||
| 		buttonGradateA: '@accent', | ||||
| 		buttonGradateB: ':hue<20<@accent', | ||||
| 		htmlThemeColor: '@bg', | ||||
| 		panelHighlight: ':lighten<3<@panel', | ||||
| 		listItemHoverBg: 'rgba(255, 255, 255, 0.03)', | ||||
| 		scrollbarHandle: 'rgba(255, 255, 255, 0.2)', | ||||
| 		inputBorderHover: 'rgba(255, 255, 255, 0.2)', | ||||
| 		wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', | ||||
| 		fgTransparentWeak: ':alpha<0.75<@fg', | ||||
| 		panelHeaderDivider: 'rgba(0, 0, 0, 0)', | ||||
| 		scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)', | ||||
| 	}, | ||||
| } | ||||
|  | @ -9,7 +9,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import {  } from 'vue'; | ||||
| import { } from 'vue'; | ||||
| import XColumn from './column.vue'; | ||||
| import XTimeline from '@/components/timeline.vue'; | ||||
| import * as os from '@/os'; | ||||
|  |  | |||
|  | @ -39,15 +39,15 @@ let pointsRenote: any = $ref(null); | |||
| let pointsTotal: any = $ref(null); | ||||
| 
 | ||||
| function dragListen(fn) { | ||||
| 	window.addEventListener('mousemove',  fn); | ||||
| 	window.addEventListener('mousemove', fn); | ||||
| 	window.addEventListener('mouseleave', dragClear.bind(null, fn)); | ||||
| 	window.addEventListener('mouseup',    dragClear.bind(null, fn)); | ||||
| 	window.addEventListener('mouseup', dragClear.bind(null, fn)); | ||||
| } | ||||
| 
 | ||||
| function dragClear(fn) { | ||||
| 	window.removeEventListener('mousemove',  fn); | ||||
| 	window.removeEventListener('mousemove', fn); | ||||
| 	window.removeEventListener('mouseleave', dragClear); | ||||
| 	window.removeEventListener('mouseup',    dragClear); | ||||
| 	window.removeEventListener('mouseup', dragClear); | ||||
| } | ||||
| 
 | ||||
| function onMousedown(ev) { | ||||
|  |  | |||
|  | @ -2866,12 +2866,12 @@ merge2@^1.3.0, merge2@^1.4.1: | |||
|   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" | ||||
|   integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== | ||||
| 
 | ||||
| mfm-js@0.22.1: | ||||
|   version "0.22.1" | ||||
|   resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.22.1.tgz#ad5f0b95cc903ca5a5e414e2edf64ac4648dc8c2" | ||||
|   integrity sha512-UV5zvDKlWPpBFeABhyCzuOTJ3RwrNrmVpJ+zz/dFX6D/ntEywljgxkfsLamcy0ZSwUAr0O+WQxGHvAwyxUgsAQ== | ||||
| mfm-js@0.23.0-canary.1: | ||||
|   version "0.23.0-canary.1" | ||||
|   resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.23.0-canary.1.tgz#1b7b7635f18bed9776054406b72e6bd613c8d0eb" | ||||
|   integrity sha512-SkMrW1rQAv+mFGtLKN9DSv6vxSREDu8ChmkBl1Ch5sQfp47BhuvcRg5EKGmt3WAQRAOylXYMg8wVYR7C5BHKeA== | ||||
|   dependencies: | ||||
|     twemoji-parser "14.0.x" | ||||
|     twemoji-parser "14.0.0" | ||||
| 
 | ||||
| micromatch@^4.0.2: | ||||
|   version "4.0.2" | ||||
|  | @ -4085,7 +4085,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: | |||
|   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" | ||||
|   integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= | ||||
| 
 | ||||
| twemoji-parser@14.0.0, twemoji-parser@14.0.x: | ||||
| twemoji-parser@14.0.0: | ||||
|   version "14.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62" | ||||
|   integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA== | ||||
|  |  | |||
|  | @ -53,7 +53,6 @@ module.exports = { | |||
| 		'no-empty-pattern': ['warn'], | ||||
| 		'no-async-promise-executor': ['off'], | ||||
| 		'no-useless-escape': ['off'], | ||||
| 		'no-multi-spaces': ['warn'], | ||||
| 		'no-multiple-empty-lines': ['error', { 'max': 1 }], | ||||
| 		'no-control-regex': ['warn'], | ||||
| 		'no-empty': ['warn'], | ||||
|  |  | |||
|  | @ -42,8 +42,12 @@ self.addEventListener('push', ev => { | |||
| 			// case 'driveFileCreated':
 | ||||
| 			case 'notification': | ||||
| 			case 'unreadMessagingMessage': | ||||
| 				// 1日以上経過している場合は無視
 | ||||
| 				if ((new Date()).getTime() - data.dateTime > 1000 * 60 * 60 * 24) break; | ||||
| 
 | ||||
| 				// クライアントがあったらストリームに接続しているということなので通知しない
 | ||||
| 				if (clients.length != 0) return; | ||||
| 				if (clients.length !== 0) break; | ||||
| 
 | ||||
| 				return createNotification(data); | ||||
| 			case 'readAllNotifications': | ||||
| 				for (const n of await self.registration.getNotifications()) { | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ export type pushNotificationData<K extends keyof pushNotificationDataSourceMap> | |||
| 	type: K; | ||||
| 	body: pushNotificationDataSourceMap[K]; | ||||
| 	userId: string; | ||||
| 	dateTime: number; | ||||
| }; | ||||
| 
 | ||||
| export type pushNotificationDataMap = { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue