Merge remote-branch 'misskey/develop'
This commit is contained in:
commit
8f65b96d82
|
@ -31,6 +31,7 @@
|
|||
- Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83)
|
||||
- Feat: TL上からノートが見えなくなるワードミュートであるハードミュートを追加
|
||||
- Enhance: アイコンデコレーションを複数設定できるように
|
||||
- Enhance: アイコンデコレーションの位置を微調整できるように
|
||||
- Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正
|
||||
|
||||
### Client
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
_lang_: "English"
|
||||
cannotBeUsedFunc: "This feature is currently unavailable."
|
||||
Xcoordinate: "X-Coordinate"
|
||||
Ycoordinate: "Y-Coordinate"
|
||||
scale: "Scale"
|
||||
opacity: "Opacity"
|
||||
noteUpdatedAt: "Edited: {date} {time}"
|
||||
|
|
2
locales/index.d.ts
vendored
2
locales/index.d.ts
vendored
|
@ -4,8 +4,6 @@
|
|||
export interface Locale {
|
||||
"_lang_": string;
|
||||
"cannotBeUsedFunc": string;
|
||||
"Xcoordinate": string;
|
||||
"Ycoordinate": string;
|
||||
"scale": string;
|
||||
"opacity": string;
|
||||
"noteUpdatedAt": string;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
_lang_: "日本語"
|
||||
|
||||
cannotBeUsedFunc: "この機能は現在使用できません。"
|
||||
Xcoordinate: "X座標"
|
||||
Ycoordinate: "Y座標"
|
||||
scale: "大きさ"
|
||||
opacity: "不透明度"
|
||||
noteUpdatedAt: "編集済み: {date} {time}"
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
_lang_: "한국어"
|
||||
cannotBeUsedFunc: "이 기능은 현재 사용할 수 없어요."
|
||||
Xcoordinate: "X 좌표"
|
||||
Ycoordinate: "Y 좌표"
|
||||
scale: "크기"
|
||||
opacity: "불투명도"
|
||||
noteUpdatedAt: "편집됨: {date} {time}"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"migrateandstart": "pnpm migrate && pnpm start",
|
||||
"migrateandstart:docker": "pnpm migrate && exec pnpm start:docker",
|
||||
"watch": "pnpm dev",
|
||||
"dev": "pnpm -r dev",
|
||||
"dev": "node scripts/dev.mjs",
|
||||
"lint": "pnpm -r lint",
|
||||
"cy:open": "pnpm cypress open --browser --e2e --config-file=cypress.config.ts",
|
||||
"cy:run": "pnpm cypress run",
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
"watch:swc": "swc src -d built -D -w",
|
||||
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
||||
"watch": "node watch.mjs",
|
||||
"dev": "node ./built/boot/entry.js",
|
||||
"restart": "pnpm build && pnpm start",
|
||||
"dev": "nodemon -w src -e ts,js,mjs,cjs,json --exec \"cross-env NODE_ENV=development pnpm run restart\"",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"eslint": "eslint --quiet \"src/**/*.ts\"",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
|
@ -231,6 +232,7 @@
|
|||
"execa": "8.0.1",
|
||||
"jest": "29.7.0",
|
||||
"jest-mock": "29.7.0",
|
||||
"nodemon": "3.0.2",
|
||||
"simple-oauth2": "5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,9 +189,9 @@ export class AvatarDecorationService implements OnApplicationShutdown {
|
|||
id: findDecoration?.id ?? '',
|
||||
angle: avatarDecorations.angle ?? 0,
|
||||
flipH: avatarDecorations.flipH ?? false,
|
||||
offsetX: avatarDecorations.offsetX ?? 0,
|
||||
offsetY: avatarDecorations.offsetY ?? 0,
|
||||
scale: avatarDecorations.scale ?? 1,
|
||||
moveX: avatarDecorations.moveX ?? 0,
|
||||
moveY: avatarDecorations.moveY ?? 0,
|
||||
opacity: avatarDecorations.opacity ?? 1,
|
||||
}];
|
||||
await this.usersRepository.update({ id: user.id }, updates);
|
||||
|
|
|
@ -398,9 +398,9 @@ export class UserEntityService implements OnModuleInit {
|
|||
id: ud.id,
|
||||
angle: ud.angle || undefined,
|
||||
flipH: ud.flipH || undefined,
|
||||
offsetX: ud.offsetX || undefined,
|
||||
offsetY: ud.offsetY || undefined,
|
||||
scale: ud.scale || undefined,
|
||||
moveX: ud.moveX || undefined,
|
||||
moveY: ud.moveY || undefined,
|
||||
opacity: ud.opacity || undefined,
|
||||
url: decorations.find(d => d.id === ud.id)!.url,
|
||||
}))) : [],
|
||||
|
|
|
@ -143,12 +143,12 @@ export class MiUser {
|
|||
})
|
||||
public avatarDecorations: {
|
||||
id: string;
|
||||
angle: number;
|
||||
flipH: boolean;
|
||||
scale: number;
|
||||
moveX: number;
|
||||
moveY: number;
|
||||
opacity: number;
|
||||
angle?: number;
|
||||
flipH?: boolean;
|
||||
offsetX?: number;
|
||||
offsetY?: number;
|
||||
scale?: number;
|
||||
opacity?: number;
|
||||
}[];
|
||||
|
||||
@Index()
|
||||
|
|
|
@ -69,18 +69,18 @@ export const packedUserLiteSchema = {
|
|||
type: 'boolean',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
offsetX: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
offsetY: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
scale: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
moveX: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
moveY: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
opacity: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
|
|
|
@ -143,9 +143,9 @@ export const paramDef = {
|
|||
id: { type: 'string', format: 'misskey:id' },
|
||||
angle: { type: 'number', nullable: true, maximum: 0.5, minimum: -0.5 },
|
||||
flipH: { type: 'boolean', nullable: true },
|
||||
offsetX: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 },
|
||||
offsetY: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 },
|
||||
scale: { type: 'number', nullable: true, maximum: 1.5, minimum: 0.5 },
|
||||
moveX: { type: 'number', nullable: true, maximum: 25, minimum: -25 },
|
||||
moveY: { type: 'number', nullable: true, maximum: 25, minimum: -25 },
|
||||
opacity: { type: 'number', nullable: true, maximum: 1, minimum: 0.1 },
|
||||
},
|
||||
required: ['id'],
|
||||
|
@ -345,9 +345,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
id: d.id,
|
||||
angle: d.angle ?? 0,
|
||||
flipH: d.flipH ?? false,
|
||||
offsetX: d.offsetX ?? 0,
|
||||
offsetY: d.offsetY ?? 0,
|
||||
scale: d.scale ?? 1,
|
||||
moveX: d.moveX ?? 0,
|
||||
moveY: d.moveY ?? 0,
|
||||
opacity: d.opacity ?? 1,
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"types": "./built/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "nodemon -w src -e ts,js,cjs,mjs,json --exec \"pnpm run build\"",
|
||||
"tsd": "tsd",
|
||||
"api": "pnpm api-extractor run --local --verbose",
|
||||
"api-prod": "pnpm api-extractor run --verbose",
|
||||
|
@ -32,9 +33,10 @@
|
|||
"jest-fetch-mock": "3.0.3",
|
||||
"jest-websocket-mock": "2.5.0",
|
||||
"mock-socket": "9.3.1",
|
||||
"ncp": "2.0.0",
|
||||
"nodemon": "3.0.2",
|
||||
"tsd": "0.29.0",
|
||||
"typescript": "5.3.3",
|
||||
"ncp": "2.0.0"
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
"files": [
|
||||
"built"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* version: 4.6.0-beta.4
|
||||
* basedMisskeyVersion: 2023.12.0-beta.4
|
||||
* generatedAt: 2023-12-14T16:00:54.542Z
|
||||
* generatedAt: 2023-12-14T17:47:05.660Z
|
||||
*/
|
||||
|
||||
import type { SwitchCaseResponseType } from '../api.js';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* version: 4.6.0-beta.4
|
||||
* basedMisskeyVersion: 2023.12.0-beta.4
|
||||
* generatedAt: 2023-12-14T16:00:54.540Z
|
||||
* generatedAt: 2023-12-14T17:47:05.658Z
|
||||
*/
|
||||
|
||||
import type {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* version: 4.6.0-beta.4
|
||||
* basedMisskeyVersion: 2023.12.0-beta.4
|
||||
* generatedAt: 2023-12-14T16:00:54.539Z
|
||||
* generatedAt: 2023-12-14T17:47:05.657Z
|
||||
*/
|
||||
|
||||
import { operations } from './types.js';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* version: 4.6.0-beta.4
|
||||
* basedMisskeyVersion: 2023.12.0-beta.4
|
||||
* generatedAt: 2023-12-14T16:00:54.537Z
|
||||
* generatedAt: 2023-12-14T17:47:05.656Z
|
||||
*/
|
||||
|
||||
import { components } from './types.js';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/*
|
||||
* version: 4.6.0-beta.4
|
||||
* basedMisskeyVersion: 2023.12.0-beta.4
|
||||
* generatedAt: 2023-12-14T16:00:54.457Z
|
||||
* generatedAt: 2023-12-14T17:47:05.577Z
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -3757,9 +3757,9 @@ export type components = {
|
|||
id: string;
|
||||
angle?: number;
|
||||
flipH?: boolean;
|
||||
offsetX?: number;
|
||||
offsetY?: number;
|
||||
scale?: number;
|
||||
moveX?: number;
|
||||
moveY?: number;
|
||||
opacity?: number;
|
||||
/** Format: url */
|
||||
url: string;
|
||||
|
@ -18674,9 +18674,9 @@ export type operations = {
|
|||
id: string;
|
||||
angle?: number | null;
|
||||
flipH?: boolean | null;
|
||||
offsetX?: number | null;
|
||||
offsetY?: number | null;
|
||||
scale?: number | null;
|
||||
moveX?: number | null;
|
||||
moveY?: number | null;
|
||||
opacity?: number | null;
|
||||
})[];
|
||||
/** Format: misskey:id */
|
||||
|
|
3
packages/frontend/@types/global.d.ts
vendored
3
packages/frontend/@types/global.d.ts
vendored
|
@ -14,3 +14,6 @@ declare const _PERF_PREFIX_: string;
|
|||
declare const _DATA_TRANSFER_DRIVE_FILE_: string;
|
||||
declare const _DATA_TRANSFER_DRIVE_FOLDER_: string;
|
||||
declare const _DATA_TRANSFER_DECK_COLUMN_: string;
|
||||
|
||||
// for dev-mode
|
||||
declare const _LANGS_FULL_: string[][];
|
||||
|
|
|
@ -8,4 +8,88 @@
|
|||
// (pnpm start時はpugファイルの中で静的リソースとして読み込むようになっており、この問題は起こっていない)
|
||||
import '@tabler/icons-webfont/tabler-icons.scss';
|
||||
|
||||
await main();
|
||||
|
||||
import('@/_boot_.js');
|
||||
|
||||
/**
|
||||
* backend/src/server/web/boot.jsで差し込まれている起動処理のうち、最低限必要なものを模倣するための処理
|
||||
*/
|
||||
async function main() {
|
||||
const forceError = localStorage.getItem('forceError');
|
||||
if (forceError != null) {
|
||||
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
|
||||
}
|
||||
|
||||
//#region Detect language & fetch translations
|
||||
|
||||
// dev-modeの場合は常に取り直す
|
||||
const supportedLangs = _LANGS_.map(it => it[0]);
|
||||
let lang: string | null | undefined = localStorage.getItem('lang');
|
||||
if (lang == null || !supportedLangs.includes(lang)) {
|
||||
if (supportedLangs.includes(navigator.language)) {
|
||||
lang = navigator.language;
|
||||
} else {
|
||||
lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
|
||||
|
||||
// Fallback
|
||||
if (lang == null) lang = 'en-US';
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:今のままだと言語ファイル変更後はpnpm devをリスタートする必要があるので、chokidarを使ったり等で対応できるようにする
|
||||
const locale = _LANGS_FULL_.find(it => it[0] === lang);
|
||||
localStorage.setItem('lang', lang);
|
||||
localStorage.setItem('locale', JSON.stringify(locale[1]));
|
||||
localStorage.setItem('localeVersion', _VERSION_);
|
||||
//#endregion
|
||||
|
||||
//#region Theme
|
||||
const theme = localStorage.getItem('theme');
|
||||
if (theme) {
|
||||
for (const [k, v] of Object.entries(JSON.parse(theme))) {
|
||||
document.documentElement.style.setProperty(`--${k}`, v.toString());
|
||||
|
||||
// HTMLの theme-color 適用
|
||||
if (k === 'htmlThemeColor') {
|
||||
for (const tag of document.head.children) {
|
||||
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
|
||||
tag.setAttribute('content', v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const colorScheme = localStorage.getItem('colorScheme');
|
||||
if (colorScheme) {
|
||||
document.documentElement.style.setProperty('color-scheme', colorScheme);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const fontSize = localStorage.getItem('fontSize');
|
||||
if (fontSize) {
|
||||
document.documentElement.classList.add('f-' + fontSize);
|
||||
}
|
||||
|
||||
const useSystemFont = localStorage.getItem('useSystemFont');
|
||||
if (useSystemFont) {
|
||||
document.documentElement.classList.add('useSystemFont');
|
||||
}
|
||||
|
||||
const wallpaper = localStorage.getItem('wallpaper');
|
||||
if (wallpaper) {
|
||||
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
|
||||
}
|
||||
|
||||
const customCss = localStorage.getItem('customCss');
|
||||
if (customCss && customCss.length > 0) {
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = customCss;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
function renderError(code: string, details?: string) {
|
||||
console.log(code, details);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { compareVersions } from 'compare-versions';
|
|||
import widgets from '@/widgets/index.js';
|
||||
import directives from '@/directives/index.js';
|
||||
import components from '@/components/index.js';
|
||||
import { version, basedMisskeyVersion, ui, lang, updateLocale } from '@/config.js';
|
||||
import { version, basedMisskeyVersion, ui, lang, updateLocale, locale } from '@/config.js';
|
||||
import { applyTheme } from '@/scripts/theme.js';
|
||||
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js';
|
||||
import { i18n, updateI18n } from '@/i18n.js';
|
||||
|
@ -101,7 +101,7 @@ export async function common(createVue: () => App<Element>) {
|
|||
|
||||
//#region Detect language & fetch translations
|
||||
const localeVersion = miLocalStorage.getItem('localeVersion');
|
||||
const localeOutdated = (localeVersion == null || localeVersion !== version || lastBasedMisskeyVersion !== basedMisskeyVersion);
|
||||
const localeOutdated = (localeVersion == null || localeVersion !== version || lastBasedMisskeyVersion !== basedMisskeyVersion || locale == null);
|
||||
if (localeOutdated) {
|
||||
const res = await window.fetch(`/assets/locales/${lang}.${version}.json`);
|
||||
if (res.status === 200) {
|
||||
|
|
|
@ -25,6 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:style="{
|
||||
rotate: getDecorationAngle(decoration),
|
||||
scale: getDecorationScale(decoration),
|
||||
translate: getDecorationOffset(decoration),
|
||||
transform: getDecorationTransform(decoration),
|
||||
opacity: getDecorationOpacity(decoration),
|
||||
}"
|
||||
|
@ -91,11 +92,15 @@ function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avat
|
|||
return scaleX === 1 ? undefined : `${scaleX} 1`;
|
||||
}
|
||||
|
||||
function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const offsetX = decoration.offsetX ?? 0;
|
||||
const offsetY = decoration.offsetY ?? 0;
|
||||
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
|
||||
}
|
||||
|
||||
function getDecorationTransform(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const scale = decoration.scale ?? 1;
|
||||
const moveX = decoration.moveX ?? 0;
|
||||
const moveY = decoration.moveY ?? 0;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`} ${moveX === 0 && moveY === 0 ? '' : `translate(${moveX}%, ${moveY}%)`}`;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`}`;
|
||||
}
|
||||
|
||||
function getDecorationOpacity(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
|
|
|
@ -41,6 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:style="{
|
||||
rotate: getDecorationAngle(decoration),
|
||||
scale: getDecorationScale(decoration),
|
||||
translate: getDecorationOffset(decoration),
|
||||
transform: getDecorationTransform(decoration),
|
||||
opacity: getDecorationOpacity(decoration),
|
||||
}"
|
||||
|
@ -63,7 +64,6 @@ import { defaultStore } from '@/store.js';
|
|||
|
||||
const animation = ref(defaultStore.state.animation);
|
||||
const squareAvatars = ref(defaultStore.state.squareAvatars);
|
||||
const useBlurEffect = ref(defaultStore.state.useBlurEffect);
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
@ -114,11 +114,15 @@ function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avat
|
|||
return scaleX === 1 ? undefined : `${scaleX} 1`;
|
||||
}
|
||||
|
||||
function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const offsetX = decoration.offsetX ?? 0;
|
||||
const offsetY = decoration.offsetY ?? 0;
|
||||
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
|
||||
}
|
||||
|
||||
function getDecorationTransform(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const scale = decoration.scale ?? 1;
|
||||
const moveX = decoration.moveX ?? 0;
|
||||
const moveY = decoration.moveY ?? 0;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`} ${moveX === 0 && moveY === 0 ? '' : `translate(${moveX}%, ${moveY}%)`}`;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`}`;
|
||||
}
|
||||
|
||||
function getDecorationOpacity(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
|
|
|
@ -24,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:style="{
|
||||
rotate: getDecorationAngle(decoration),
|
||||
scale: getDecorationScale(decoration),
|
||||
translate: getDecorationOffset(decoration),
|
||||
transform: getDecorationTransform(decoration),
|
||||
opacity: getDecorationOpacity(decoration),
|
||||
}"
|
||||
|
@ -85,6 +86,12 @@ function getDecorationAngle(decoration: Omit<Misskey.entities.UserDetailed['avat
|
|||
return angle === 0 ? undefined : `${angle * 360}deg`;
|
||||
}
|
||||
|
||||
function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const offsetX = decoration.offsetX ?? 0;
|
||||
const offsetY = decoration.offsetY ?? 0;
|
||||
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
|
||||
}
|
||||
|
||||
function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const scaleX = decoration.flipH ? -1 : 1;
|
||||
return scaleX === 1 ? undefined : `${scaleX} 1`;
|
||||
|
@ -92,9 +99,7 @@ function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avat
|
|||
|
||||
function getDecorationTransform(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
const scale = decoration.scale ?? 1;
|
||||
const moveX = decoration.moveX ?? 0;
|
||||
const moveY = decoration.moveY ?? 0;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`} ${moveX === 0 && moveY === 0 ? '' : `translate(${moveX}%, ${moveY}%)`}`;
|
||||
return `${scale === 1 ? '' : `scale(${scale})`}`;
|
||||
}
|
||||
|
||||
function getDecorationOpacity(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@click="emit('click')"
|
||||
>
|
||||
<div :class="$style.name"><MkCondensedLine :minScale="0.5">{{ decoration.name }}</MkCondensedLine></div>
|
||||
<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: decoration.url, angle, flipH }]" forceShowDecoration/>
|
||||
<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: decoration.url, angle, flipH, offsetX, offsetY, scale, opacity }]" forceShowDecoration @click="emit('click')"/>
|
||||
<i v-if="decoration.roleIdsThatCanBeUsedThisDecoration.length > 0 && !$i.roles.some(r => decoration.roleIdsThatCanBeUsedThisDecoration.includes(r.id))" :class="$style.lock" class="ti ti-lock"></i>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -28,6 +28,10 @@ const props = defineProps<{
|
|||
};
|
||||
angle?: number;
|
||||
flipH?: boolean;
|
||||
offsetX?: number;
|
||||
offsetY?: number;
|
||||
scale?: number;
|
||||
opacity?: number;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkModalWindow
|
||||
ref="dialog"
|
||||
:width="400"
|
||||
:height="450"
|
||||
:height="700"
|
||||
@close="cancel"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
|
@ -23,18 +23,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkRange v-model="angle" continuousUpdate :min="-0.5" :max="0.5" :step="0.025" :textConverter="(v) => `${Math.floor(v * 360)}°`">
|
||||
<template #label>{{ i18n.ts.angle }}</template>
|
||||
</MkRange>
|
||||
<MkRange v-model="offsetX" continuousUpdate :min="-0.25" :max="0.25" :step="0.025" :textConverter="(v) => `${Math.floor(v * 100)}%`">
|
||||
<template #label>X {{ i18n.ts.position }}</template>
|
||||
</MkRange>
|
||||
<MkRange v-model="offsetY" continuousUpdate :min="-0.25" :max="0.25" :step="0.025" :textConverter="(v) => `${Math.floor(v * 100)}%`">
|
||||
<template #label>Y {{ i18n.ts.position }}</template>
|
||||
</MkRange>
|
||||
<MkSwitch v-model="flipH">
|
||||
<template #label>{{ i18n.ts.flip }}</template>
|
||||
</MkSwitch>
|
||||
<MkRange v-model="scale" continuousUpdate :min="0.5" :max="1.5" :step="0.05" :textConverter="(v) => `${v.toFixed(2)}x`">
|
||||
<template #label>{{ i18n.ts.scale }}</template>
|
||||
</MkRange>
|
||||
<MkRange v-model="moveX" continuousUpdate :min="-25" :max="25" :step="1">
|
||||
<template #label>{{ i18n.ts.Xcoordinate }}</template>
|
||||
</MkRange>
|
||||
<MkRange v-model="moveY" continuousUpdate :min="-25" :max="25" :step="1">
|
||||
<template #label>{{ i18n.ts.Ycoordinate }}</template>
|
||||
</MkRange>
|
||||
<MkRange v-model="opacity" continuousUpdate :min="0.1" :max="1" :step="0.05" :textConverter="(v) => `${(v * 100).toFixed(2)}%`">
|
||||
<template #label>{{ i18n.ts.opacity }}</template>
|
||||
</MkRange>
|
||||
|
@ -73,17 +73,17 @@ const emit = defineEmits<{
|
|||
(ev: 'attach', payload: {
|
||||
angle: number;
|
||||
flipH: boolean;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
scale: number;
|
||||
moveX: number;
|
||||
moveY: number;
|
||||
opacity: number;
|
||||
}): void;
|
||||
(ev: 'update', payload: {
|
||||
angle: number;
|
||||
flipH: boolean;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
scale: number;
|
||||
moveX: number;
|
||||
moveY: number;
|
||||
opacity: number;
|
||||
}): void;
|
||||
(ev: 'detach'): void;
|
||||
|
@ -93,9 +93,9 @@ const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
|
|||
const exceeded = computed(() => ($i.policies.avatarDecorationLimit - $i.avatarDecorations.length) <= 0);
|
||||
const angle = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].angle : null) ?? 0);
|
||||
const flipH = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].flipH : null) ?? false);
|
||||
const offsetX = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].offsetX : null) ?? 0);
|
||||
const offsetY = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].offsetY : null) ?? 0);
|
||||
const scale = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].scale : null) ?? 1);
|
||||
const moveX = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].moveX : null) ?? 0);
|
||||
const moveY = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].moveY : null) ?? 0);
|
||||
const opacity = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].opacity : null) ?? 1);
|
||||
|
||||
const decorationsForPreview = computed(() => {
|
||||
|
@ -104,9 +104,9 @@ const decorationsForPreview = computed(() => {
|
|||
url: props.decoration.url,
|
||||
angle: angle.value,
|
||||
flipH: flipH.value,
|
||||
offsetX: offsetX.value,
|
||||
offsetY: offsetY.value,
|
||||
scale: scale.value,
|
||||
moveX: moveX.value,
|
||||
moveY: moveY.value,
|
||||
opacity: opacity.value,
|
||||
};
|
||||
const decorations = [...$i.avatarDecorations];
|
||||
|
@ -126,9 +126,9 @@ async function update() {
|
|||
emit('update', {
|
||||
angle: angle.value,
|
||||
flipH: flipH.value,
|
||||
offsetX: offsetX.value,
|
||||
offsetY: offsetY.value,
|
||||
scale: scale.value,
|
||||
moveX: moveX.value,
|
||||
moveY: moveY.value,
|
||||
opacity: opacity.value,
|
||||
});
|
||||
dialog.value.close();
|
||||
|
@ -138,9 +138,9 @@ async function attach() {
|
|||
emit('attach', {
|
||||
angle: angle.value,
|
||||
flipH: flipH.value,
|
||||
offsetX: offsetX.value,
|
||||
offsetY: offsetY.value,
|
||||
scale: scale.value,
|
||||
moveX: moveX.value,
|
||||
moveY: moveY.value,
|
||||
opacity: opacity.value,
|
||||
});
|
||||
dialog.value.close();
|
||||
|
|
|
@ -16,6 +16,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:decoration="avatarDecorations.find(d => d.id === avatarDecoration.id)"
|
||||
:angle="avatarDecoration.angle"
|
||||
:flipH="avatarDecoration.flipH"
|
||||
:offsetX="avatarDecoration.offsetX"
|
||||
:offsetY="avatarDecoration.offsetY"
|
||||
:scale="avatarDecoration.scale"
|
||||
:opacity="avatarDecoration.opacity"
|
||||
:active="true"
|
||||
@click="openDecoration(avatarDecoration, i)"
|
||||
/>
|
||||
|
@ -66,6 +70,10 @@ function openDecoration(avatarDecoration, index?: number) {
|
|||
id: avatarDecoration.id,
|
||||
angle: payload.angle,
|
||||
flipH: payload.flipH,
|
||||
offsetX: payload.offsetX,
|
||||
offsetY: payload.offsetY,
|
||||
scale: payload.scale,
|
||||
opacity: payload.opacity,
|
||||
};
|
||||
const update = [...$i.avatarDecorations, decoration];
|
||||
await os.apiWithDialog('i/update', {
|
||||
|
@ -78,6 +86,10 @@ function openDecoration(avatarDecoration, index?: number) {
|
|||
id: avatarDecoration.id,
|
||||
angle: payload.angle,
|
||||
flipH: payload.flipH,
|
||||
offsetX: payload.offsetX,
|
||||
offsetY: payload.offsetY,
|
||||
scale: payload.scale,
|
||||
opacity: payload.opacity,
|
||||
};
|
||||
const update = [...$i.avatarDecorations];
|
||||
update[index] = decoration;
|
||||
|
|
|
@ -6,6 +6,7 @@ import { fetchCustomEmojis } from '@/custom-emojis.js';
|
|||
export async function clearCache() {
|
||||
os.waiting();
|
||||
miLocalStorage.removeItem('locale');
|
||||
miLocalStorage.removeItem('localeVersion');
|
||||
miLocalStorage.removeItem('theme');
|
||||
miLocalStorage.removeItem('emojis');
|
||||
miLocalStorage.removeItem('lastEmojisFetchedAt');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import dns from 'dns';
|
||||
import { defineConfig } from 'vite';
|
||||
import locales from '../../locales';
|
||||
import { getConfig } from './vite.config.js';
|
||||
|
||||
dns.setDefaultResultOrder('ipv4first');
|
||||
|
@ -49,6 +50,11 @@ const devConfig = {
|
|||
input: 'index.html',
|
||||
},
|
||||
},
|
||||
|
||||
define: {
|
||||
...defaultConfig.define,
|
||||
_LANGS_FULL_: JSON.stringify(Object.entries(locales)),
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig(({ command, mode }) => devConfig);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "sw",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"watch": "node build.js watch",
|
||||
"watch": "nodemon -w ../../package.json -e json --exec \"node build.js watch\"",
|
||||
"build": "node build.js",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"eslint": "eslint --quiet src/**/*.ts",
|
||||
|
@ -18,6 +18,7 @@
|
|||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
|
||||
"eslint": "8.55.0",
|
||||
"eslint-plugin-import": "2.29.0",
|
||||
"nodemon": "3.0.2",
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
"type": "module"
|
||||
|
|
|
@ -655,6 +655,9 @@ importers:
|
|||
jest-mock:
|
||||
specifier: 29.7.0
|
||||
version: 29.7.0
|
||||
nodemon:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
simple-oauth2:
|
||||
specifier: 5.0.0
|
||||
version: 5.0.0
|
||||
|
@ -710,6 +713,9 @@ importers:
|
|||
ncp:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0
|
||||
nodemon:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
tsd:
|
||||
specifier: 0.29.0
|
||||
version: 0.29.0
|
||||
|
@ -1150,6 +1156,9 @@ importers:
|
|||
eslint-plugin-import:
|
||||
specifier: 2.29.0
|
||||
version: 2.29.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)
|
||||
nodemon:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
typescript:
|
||||
specifier: 5.3.3
|
||||
version: 5.3.3
|
||||
|
|
|
@ -95,6 +95,7 @@ if (process.argv.includes("--watch")) {
|
|||
for await (const event of watcher) {
|
||||
const filename = event.filename?.replaceAll('\\', '/');
|
||||
if (/^[a-z]+-[A-Z]+\.yml/.test(filename)) {
|
||||
console.log(`update ${filename} ...`)
|
||||
locales = buildLocales();
|
||||
await copyFrontendLocales()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,24 @@
|
|||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const meta = require('../package.json');
|
||||
const packageJsonPath = __dirname + '/../package.json'
|
||||
|
||||
fs.mkdirSync(__dirname + '/../built', { recursive: true });
|
||||
fs.writeFileSync(__dirname + '/../built/meta.json', JSON.stringify({ version: meta.version, basedMisskeyVersion: meta.basedMisskeyVersion }), 'utf-8');
|
||||
function build() {
|
||||
try {
|
||||
const json = fs.readFileSync(packageJsonPath, 'utf-8')
|
||||
const meta = JSON.parse(json);
|
||||
fs.mkdirSync(__dirname + '/../built', { recursive: true });
|
||||
fs.writeFileSync(__dirname + '/../built/meta.json', JSON.stringify({ version: meta.version, basedMisskeyVersion: meta.basedMisskeyVersion }), 'utf-8');
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
build();
|
||||
|
||||
if (process.argv.includes("--watch")) {
|
||||
fs.watch(packageJsonPath, (event, filename) => {
|
||||
console.log(`update ${filename} ...`)
|
||||
build()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { execa } from 'execa';
|
||||
|
@ -11,8 +10,6 @@ import { execa } from 'execa';
|
|||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
||||
const vitePort = process.env.VITE_PORT ? ["--strictPort", "--port", process.env.VITE_PORT] : ["--strictPort"];
|
||||
|
||||
await execa('pnpm', ['clean'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
|
@ -31,19 +28,25 @@ await execa('pnpm', ['build-assets'], {
|
|||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
execa('pnpm', ['build-pre', '--watch'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
execa('pnpm', ['build-assets', '--watch'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
execa('pnpm', ['--filter', 'backend', 'watch'], {
|
||||
execa('pnpm', ['--filter', 'backend', 'dev'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
execa('pnpm', ['--filter', 'frontend', 'watch', ...vitePort], {
|
||||
execa('pnpm', ['--filter', 'frontend', 'dev'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
|
@ -55,27 +58,8 @@ execa('pnpm', ['--filter', 'sw', 'watch'], {
|
|||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
const start = async () => {
|
||||
try {
|
||||
const stat = fs.statSync(_dirname + '/../packages/backend/built/boot/entry.js');
|
||||
if (!stat) throw new Error('not exist yet');
|
||||
if (stat.size === 0) throw new Error('not built yet');
|
||||
|
||||
const subprocess = await execa('pnpm', ['start'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
||||
// なぜかworkerだけが終了してmasterが残るのでその対策
|
||||
process.on('SIGINT', () => {
|
||||
subprocess.kill('SIGINT');
|
||||
process.exit(0);
|
||||
});
|
||||
} catch (e) {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
start();
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
execa('pnpm', ['--filter', 'cherrypick-js', 'watch'], {
|
||||
cwd: _dirname + '/../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue