Merge branch 'develop' into sw-notification-action
This commit is contained in:
commit
17f59de458
41 changed files with 1016 additions and 679 deletions
|
@ -761,6 +761,9 @@ middle: "中"
|
|||
low: "低"
|
||||
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
|
||||
ratio: "比率"
|
||||
customCss: "カスタムCSS"
|
||||
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
|
||||
global: "グローバル"
|
||||
|
||||
_ad:
|
||||
back: "戻る"
|
||||
|
|
152
package.json
152
package.json
|
@ -34,7 +34,7 @@
|
|||
"lodash": "^4.17.21"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-runtime": "7.14.3",
|
||||
"@babel/plugin-transform-runtime": "7.14.5",
|
||||
"@elastic/elasticsearch": "7.11.0",
|
||||
"@koa/cors": "3.1.0",
|
||||
"@koa/multer": "3.0.0",
|
||||
|
@ -44,94 +44,94 @@
|
|||
"@sinonjs/fake-timers": "7.1.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.15.1",
|
||||
"@types/bull": "3.15.2",
|
||||
"@types/cbor": "6.0.0",
|
||||
"@types/dateformat": "3.0.1",
|
||||
"@types/escape-regexp": "0.0.0",
|
||||
"@types/glob": "7.1.3",
|
||||
"@types/gulp": "4.0.8",
|
||||
"@types/gulp-rename": "2.0.0",
|
||||
"@types/is-url": "1.2.29",
|
||||
"@types/js-yaml": "4.0.1",
|
||||
"@types/jsdom": "16.2.10",
|
||||
"@types/jsonld": "1.5.5",
|
||||
"@types/katex": "0.11.0",
|
||||
"@types/koa": "2.13.3",
|
||||
"@types/koa-bodyparser": "4.3.1",
|
||||
"@types/koa-cors": "0.0.0",
|
||||
"@types/koa-favicon": "2.0.19",
|
||||
"@types/glob": "7.1.4",
|
||||
"@types/gulp": "4.0.9",
|
||||
"@types/gulp-rename": "2.0.1",
|
||||
"@types/is-url": "1.2.30",
|
||||
"@types/js-yaml": "4.0.2",
|
||||
"@types/jsdom": "16.2.13",
|
||||
"@types/jsonld": "1.5.6",
|
||||
"@types/katex": "0.11.1",
|
||||
"@types/koa": "2.13.4",
|
||||
"@types/koa-bodyparser": "4.3.2",
|
||||
"@types/koa-cors": "0.0.1",
|
||||
"@types/koa-favicon": "2.0.21",
|
||||
"@types/koa-logger": "3.1.1",
|
||||
"@types/koa-mount": "4.0.0",
|
||||
"@types/koa-send": "4.1.2",
|
||||
"@types/koa-send": "4.1.3",
|
||||
"@types/koa-views": "7.0.0",
|
||||
"@types/koa__cors": "3.0.2",
|
||||
"@types/koa__multer": "2.0.2",
|
||||
"@types/koa__router": "8.0.4",
|
||||
"@types/markdown-it": "12.0.2",
|
||||
"@types/matter-js": "0.14.12",
|
||||
"@types/mocha": "8.2.2",
|
||||
"@types/node": "15.12.2",
|
||||
"@types/node-fetch": "2.5.10",
|
||||
"@types/nodemailer": "6.4.2",
|
||||
"@types/koa__cors": "3.0.3",
|
||||
"@types/koa__multer": "2.0.3",
|
||||
"@types/koa__router": "8.0.7",
|
||||
"@types/markdown-it": "12.0.3",
|
||||
"@types/matter-js": "0.17.3",
|
||||
"@types/mocha": "8.2.3",
|
||||
"@types/node": "16.3.3",
|
||||
"@types/node-fetch": "2.5.11",
|
||||
"@types/nodemailer": "6.4.4",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/parse5": "6.0.0",
|
||||
"@types/parse5": "6.0.1",
|
||||
"@types/parsimmon": "1.10.6",
|
||||
"@types/portscanner": "2.1.0",
|
||||
"@types/pug": "2.0.4",
|
||||
"@types/portscanner": "2.1.1",
|
||||
"@types/pug": "2.0.5",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/qrcode": "1.4.0",
|
||||
"@types/qrcode": "1.4.1",
|
||||
"@types/random-seed": "0.3.3",
|
||||
"@types/ratelimiter": "3.4.1",
|
||||
"@types/redis": "2.8.29",
|
||||
"@types/rename": "1.0.3",
|
||||
"@types/ratelimiter": "3.4.2",
|
||||
"@types/redis": "2.8.31",
|
||||
"@types/rename": "1.0.4",
|
||||
"@types/request-stats": "3.0.0",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/rimraf": "3.0.1",
|
||||
"@types/seedrandom": "2.4.28",
|
||||
"@types/sharp": "0.28.3",
|
||||
"@types/sinonjs__fake-timers": "6.0.2",
|
||||
"@types/speakeasy": "2.0.5",
|
||||
"@types/sharp": "0.28.4",
|
||||
"@types/sinonjs__fake-timers": "6.0.3",
|
||||
"@types/speakeasy": "2.0.6",
|
||||
"@types/throttle-debounce": "2.1.0",
|
||||
"@types/tinycolor2": "1.4.2",
|
||||
"@types/tmp": "0.2.0",
|
||||
"@types/uuid": "8.3.0",
|
||||
"@types/web-push": "3.3.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/tmp": "0.2.1",
|
||||
"@types/uuid": "8.3.1",
|
||||
"@types/web-push": "3.3.2",
|
||||
"@types/webpack": "5.28.0",
|
||||
"@types/webpack-stream": "3.2.12",
|
||||
"@types/websocket": "1.0.2",
|
||||
"@types/ws": "7.4.4",
|
||||
"@typescript-eslint/parser": "4.26.1",
|
||||
"@vue/compiler-sfc": "3.1.1",
|
||||
"@types/websocket": "1.0.3",
|
||||
"@types/ws": "7.4.6",
|
||||
"@typescript-eslint/parser": "4.28.3",
|
||||
"@vue/compiler-sfc": "3.1.5",
|
||||
"abort-controller": "3.0.0",
|
||||
"apexcharts": "3.27.1",
|
||||
"apexcharts": "3.27.2",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "4.0.4",
|
||||
"autwh": "0.1.0",
|
||||
"aws-sdk": "2.923.0",
|
||||
"aws-sdk": "2.948.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "1.1.3",
|
||||
"broadcast-channel": "3.6.0",
|
||||
"bull": "3.22.7",
|
||||
"broadcast-channel": "3.7.0",
|
||||
"bull": "3.26.0",
|
||||
"cafy": "15.2.1",
|
||||
"cbor": "7.0.5",
|
||||
"cbor": "7.0.6",
|
||||
"chalk": "4.1.1",
|
||||
"chart.js": "2.9.4",
|
||||
"cli-highlight": "2.1.11",
|
||||
"commander": "7.2.0",
|
||||
"concurrently": "6.2.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"core-js": "3.14.0",
|
||||
"core-js": "3.15.2",
|
||||
"crc-32": "1.2.0",
|
||||
"css-loader": "5.2.6",
|
||||
"cssnano": "5.0.5",
|
||||
"css-loader": "6.0.0",
|
||||
"cssnano": "5.0.6",
|
||||
"dateformat": "4.5.1",
|
||||
"diskusage": "1.1.3",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "7.28.0",
|
||||
"eslint-plugin-vue": "7.10.0",
|
||||
"eslint": "7.30.0",
|
||||
"eslint-plugin-vue": "7.13.0",
|
||||
"eventemitter3": "4.0.7",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "16.5.0",
|
||||
"file-type": "16.5.1",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"glob": "7.1.7",
|
||||
"got": "11.8.2",
|
||||
|
@ -154,7 +154,7 @@
|
|||
"jsdom": "16.6.0",
|
||||
"json5": "2.2.0",
|
||||
"json5-loader": "4.0.1",
|
||||
"jsonld": "4.0.1",
|
||||
"jsonld": "5.2.0",
|
||||
"jsrsasign": "8.0.20",
|
||||
"katex": "0.13.11",
|
||||
"koa": "2.13.1",
|
||||
|
@ -168,26 +168,26 @@
|
|||
"koa-views": "7.0.1",
|
||||
"langmap": "0.0.16",
|
||||
"lookup-dns-cache": "2.1.0",
|
||||
"markdown-it": "12.0.6",
|
||||
"markdown-it": "12.1.0",
|
||||
"markdown-it-anchor": "7.1.0",
|
||||
"matter-js": "0.17.1",
|
||||
"mfm-js": "0.18.0",
|
||||
"misskey-js": "0.0.4",
|
||||
"mfm-js": "0.19.0",
|
||||
"misskey-js": "0.0.6",
|
||||
"mocha": "8.4.0",
|
||||
"moji": "0.5.1",
|
||||
"ms": "2.1.3",
|
||||
"multer": "1.4.2",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"nodemailer": "6.6.1",
|
||||
"nodemailer": "6.6.3",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"os-utils": "0.0.14",
|
||||
"parse5": "6.0.1",
|
||||
"pg": "8.6.0",
|
||||
"portscanner": "2.2.0",
|
||||
"postcss": "8.3.0",
|
||||
"postcss-loader": "5.3.0",
|
||||
"prismjs": "1.23.0",
|
||||
"postcss": "8.3.5",
|
||||
"postcss-loader": "6.1.1",
|
||||
"prismjs": "1.24.1",
|
||||
"probe-image-size": "7.2.1",
|
||||
"promise-limit": "2.7.0",
|
||||
"promise-sequential": "1.1.1",
|
||||
|
@ -209,16 +209,16 @@
|
|||
"rimraf": "3.0.2",
|
||||
"rndstr": "1.0.0",
|
||||
"s-age": "1.1.2",
|
||||
"sass": "1.34.1",
|
||||
"sass-loader": "12.0.0",
|
||||
"sass": "1.35.2",
|
||||
"sass-loader": "12.1.0",
|
||||
"seedrandom": "3.0.5",
|
||||
"sharp": "0.28.3",
|
||||
"speakeasy": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"style-loader": "2.0.0",
|
||||
"style-loader": "3.1.0",
|
||||
"summaly": "2.4.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
"systeminformation": "5.7.4",
|
||||
"systeminformation": "5.7.7",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.117.1",
|
||||
|
@ -226,32 +226,32 @@
|
|||
"tinycolor2": "1.4.2",
|
||||
"tmp": "0.2.1",
|
||||
"ts-loader": "9.2.3",
|
||||
"ts-node": "10.0.0",
|
||||
"tsc-alias": "1.3.2",
|
||||
"tsconfig-paths": "3.9.0",
|
||||
"ts-node": "10.1.0",
|
||||
"tsc-alias": "1.3.7",
|
||||
"tsconfig-paths": "3.10.1",
|
||||
"tslint": "6.1.3",
|
||||
"tslint-sonarts": "1.9.0",
|
||||
"twemoji-parser": "13.1.0",
|
||||
"typeorm": "0.2.32",
|
||||
"typescript": "4.3.2",
|
||||
"typescript": "4.3.5",
|
||||
"ulid": "2.3.0",
|
||||
"uuid": "8.3.2",
|
||||
"v-debounce": "0.1.2",
|
||||
"vanilla-tilt": "1.7.0",
|
||||
"vue": "3.1.1",
|
||||
"vue": "3.1.5",
|
||||
"vue-color": "2.8.1",
|
||||
"vue-json-pretty": "1.7.1",
|
||||
"vue-loader": "16.1.2",
|
||||
"vue-json-pretty": "1.8.1",
|
||||
"vue-loader": "16.3.1",
|
||||
"vue-prism-editor": "2.0.0-alpha.2",
|
||||
"vue-router": "4.0.5",
|
||||
"vue-style-loader": "4.1.3",
|
||||
"vue-svg-loader": "0.17.0-beta.2",
|
||||
"vuedraggable": "4.0.1",
|
||||
"web-push": "3.4.4",
|
||||
"webpack": "5.38.1",
|
||||
"web-push": "3.4.5",
|
||||
"webpack": "5.45.1",
|
||||
"webpack-cli": "4.7.2",
|
||||
"websocket": "1.0.34",
|
||||
"ws": "7.4.6",
|
||||
"ws": "7.5.3",
|
||||
"xev": "2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -9,6 +9,8 @@ import { unisonReload, reloadChannel } from '@client/scripts/unison-reload';
|
|||
type Account = {
|
||||
id: string;
|
||||
token: string;
|
||||
isModerator: boolean;
|
||||
isAdmin: boolean;
|
||||
};
|
||||
|
||||
const data = localStorage.getItem('account');
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="hoawjimk">
|
||||
<div class="mk-media-list">
|
||||
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/>
|
||||
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
|
||||
<div :data-count="mediaList.filter(media => previewable(media)).length">
|
||||
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container" ref="gridOuter">
|
||||
<div :data-count="mediaList.filter(media => previewable(media)).length" :style="gridInnerStyle">
|
||||
<template v-for="media in mediaList">
|
||||
<XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/>
|
||||
<XImage :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/>
|
||||
|
@ -33,16 +33,57 @@ export default defineComponent({
|
|||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
gridInnerStyle: {},
|
||||
sizeWaiting: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.size();
|
||||
window.addEventListener('resize', this.size);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.size);
|
||||
},
|
||||
activated() {
|
||||
this.size();
|
||||
},
|
||||
methods: {
|
||||
previewable(file) {
|
||||
return file.type.startsWith('video') || file.type.startsWith('image');
|
||||
},
|
||||
size() {
|
||||
// for Safari bug
|
||||
if (this.sizeWaiting) return;
|
||||
|
||||
this.sizeWaiting = true;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
this.sizeWaiting = false;
|
||||
|
||||
if (this.$refs.gridOuter) {
|
||||
let height = 287;
|
||||
const parent = this.$parent.$el;
|
||||
|
||||
if (this.$refs.gridOuter.clientHeight) {
|
||||
height = this.$refs.gridOuter.clientHeight;
|
||||
} else if (parent) {
|
||||
height = parent.getBoundingClientRect().width * 9 / 16;
|
||||
}
|
||||
|
||||
this.gridInnerStyle = { height: `${height}px` };
|
||||
} else {
|
||||
this.gridInnerStyle = {};
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.hoawjimk {
|
||||
.mk-media-list {
|
||||
> .gird-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
|
|
@ -61,7 +61,7 @@ import * as mfm from 'mfm-js';
|
|||
import { host, url } from '@client/config';
|
||||
import { erase, unique } from '../../prelude/array';
|
||||
import { extractMentions } from '@/misc/extract-mentions';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import { formatTimeString } from '@/misc/format-time-string';
|
||||
import { Autocomplete } from '@client/scripts/autocomplete';
|
||||
import { noteVisibilities } from '../../types';
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkFollowButton from './follow-button.vue';
|
||||
import { userPage } from '../filters/user';
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkFollowButton from './follow-button.vue';
|
||||
import { userPage } from '../filters/user';
|
||||
import * as os from '@client/os';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import getUserName from '@/misc/get-user-name';
|
||||
import { url } from '@client/config';
|
||||
|
||||
|
|
|
@ -77,18 +77,6 @@ console.info(`Misskey v${version}`);
|
|||
window.onerror = null;
|
||||
window.onunhandledrejection = null;
|
||||
|
||||
// 後方互換性のため。
|
||||
// TODO: そのうち消す
|
||||
if ((typeof ColdDeviceStorage.get('lightTheme') === 'string') || (typeof ColdDeviceStorage.get('darkTheme') === 'string')) {
|
||||
ColdDeviceStorage.set('lightTheme', require('@client/themes/l-light.json5'));
|
||||
ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.json5'));
|
||||
}
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = 'https://use.fontawesome.com/releases/v5.15.3/css/all.css';
|
||||
document.head.appendChild(link);
|
||||
// TODOここまで
|
||||
|
||||
if (_DEV_) {
|
||||
console.warn('Development mode!!!');
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import * as os from '@client/os';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
|
||||
export default defineComponent({
|
||||
created() {
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import MkInput from '@client/components/ui/input.vue';
|
||||
import MkSelect from '@client/components/ui/select.vue';
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import { acct } from '../../filters/user';
|
||||
import * as os from '@client/os';
|
||||
|
|
|
@ -40,7 +40,7 @@ import { computed, defineComponent } from 'vue';
|
|||
import XList from '@client/components/date-separated-list.vue';
|
||||
import XMessage from './messaging-room.message.vue';
|
||||
import XForm from './messaging-room.form.vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { isBottom, onScrollBottom, scroll } from '@client/scripts/scroll';
|
||||
import * as os from '@client/os';
|
||||
import { popout } from '@client/scripts/popout';
|
||||
|
|
|
@ -52,7 +52,7 @@ import MkInput from '@client/components/ui/input.vue';
|
|||
import MkTextarea from '@client/components/ui/textarea.vue';
|
||||
import MkSelect from '@client/components/ui/select.vue';
|
||||
import MkSwitch from '@client/components/ui/switch.vue';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { Room } from '@client/scripts/room/room';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import XPreview from './preview.vue';
|
||||
const storeItems = require('@client/scripts/room/furnitures.json5');
|
||||
import { query as urlQuery } from '../../../prelude/url';
|
||||
|
|
72
src/client/pages/settings/custom-css.vue
Normal file
72
src/client/pages/settings/custom-css.vue
Normal file
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<FormBase>
|
||||
<FormInfo warn>{{ $ts.customCssWarn }}</FormInfo>
|
||||
|
||||
<FormTextarea v-model:value="localCustomCss" manual-save tall class="_monospace" style="tab-size: 2;">
|
||||
<span>{{ $ts.local }}</span>
|
||||
</FormTextarea>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import FormTextarea from '@client/components/form/textarea.vue';
|
||||
import FormSelect from '@client/components/form/select.vue';
|
||||
import FormRadios from '@client/components/form/radios.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormLink from '@client/components/form/link.vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import FormInfo from '@client/components/form/info.vue';
|
||||
import * as os from '@client/os';
|
||||
import { ColdDeviceStorage } from '@client/store';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
import * as symbols from '@client/symbols';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormTextarea,
|
||||
FormSelect,
|
||||
FormRadios,
|
||||
FormBase,
|
||||
FormGroup,
|
||||
FormLink,
|
||||
FormButton,
|
||||
FormInfo,
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.customCss,
|
||||
icon: 'fas fa-code'
|
||||
},
|
||||
localCustomCss: localStorage.getItem('customCss')
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this[symbols.PAGE_INFO]);
|
||||
|
||||
this.$watch('localCustomCss', this.apply);
|
||||
},
|
||||
|
||||
methods: {
|
||||
async apply() {
|
||||
localStorage.setItem('customCss', this.localCustomCss);
|
||||
|
||||
const { canceled } = await os.dialog({
|
||||
type: 'info',
|
||||
text: this.$ts.reloadToApplySetting,
|
||||
showCancelButton: true
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -78,6 +78,8 @@
|
|||
</FormSelect>
|
||||
|
||||
<FormLink to="/settings/deck">{{ $ts.deck }}</FormLink>
|
||||
|
||||
<FormLink to="/settings/custom-css"><template #icon><i class="fas fa-code"></i></template>{{ $ts.customCss }}</FormLink>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ export default defineComponent({
|
|||
case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue'));
|
||||
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
|
||||
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
|
||||
case 'custom-css': return defineAsyncComponent(() => import('./custom-css.vue'));
|
||||
case 'deck': return defineAsyncComponent(() => import('./deck.vue'));
|
||||
case 'plugin': return defineAsyncComponent(() => import('./plugin.vue'));
|
||||
case 'plugin/install': return defineAsyncComponent(() => import('./plugin.install.vue'));
|
||||
|
|
|
@ -29,6 +29,7 @@ import * as os from '@client/os';
|
|||
import { sidebarDef } from '@client/sidebar';
|
||||
import { defaultStore } from '@client/store';
|
||||
import * as symbols from '@client/symbols';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
|
@ -106,7 +107,7 @@ export default defineComponent({
|
|||
});
|
||||
if (canceled) return;
|
||||
|
||||
location.reload();
|
||||
unisonReload();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -234,7 +234,7 @@ import MkRemoteCaution from '@client/components/remote-caution.vue';
|
|||
import MkTab from '@client/components/tab.vue';
|
||||
import MkInfo from '@client/components/ui/info.vue';
|
||||
import Progress from '@client/scripts/loading';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { getScrollPosition } from '@client/scripts/scroll';
|
||||
import { getUserMenu } from '@client/scripts/get-user-menu';
|
||||
import number from '../../filters/number';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { host as localHost } from '@client/config';
|
||||
|
||||
export async function genSearchQuery(v: any, q: string) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { i18n } from '@client/i18n';
|
||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||
import { host } from '@client/config';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import * as os from '@client/os';
|
||||
import { userActions } from '@client/store';
|
||||
import { router } from '@client/router';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { i18n } from '@client/i18n';
|
||||
import * as os from '@client/os';
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import * as os from '@client/os';
|
||||
import { i18n } from '@client/i18n';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
return new Promise((res, rej) => {
|
||||
|
@ -8,7 +9,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
|||
input.type = 'file';
|
||||
input.multiple = multiple;
|
||||
input.onchange = () => {
|
||||
const promises = Array.from(input.files).map(file => os.upload(file));
|
||||
const promises = Array.from(input.files).map(file => os.upload(file, defaultStore.state.uploadFolder));
|
||||
|
||||
Promise.all(promises).then(driveFiles => {
|
||||
res(multiple ? driveFiles : driveFiles[0]);
|
||||
|
@ -57,6 +58,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
|||
|
||||
os.api('drive/files/upload-from-url', {
|
||||
url: url,
|
||||
folderId: defaultStore.state.uploadFolder,
|
||||
marker
|
||||
});
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
},
|
||||
uploadFolder: {
|
||||
where: 'account',
|
||||
default: null
|
||||
default: null as string | null
|
||||
},
|
||||
pastedFileName: {
|
||||
where: 'account',
|
||||
|
|
|
@ -55,7 +55,7 @@ import * as mfm from 'mfm-js';
|
|||
import { host, url } from '@client/config';
|
||||
import { erase, unique } from '../../../prelude/array';
|
||||
import { extractMentions } from '@/misc/extract-mentions';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import { formatTimeString } from '@/misc/format-time-string';
|
||||
import { Autocomplete } from '@client/scripts/autocomplete';
|
||||
import * as os from '@client/os';
|
||||
|
|
14
src/misc/acct.ts
Normal file
14
src/misc/acct.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
export type Acct = {
|
||||
username: string;
|
||||
host: string | null;
|
||||
};
|
||||
|
||||
export const getAcct = (user: Acct) => {
|
||||
return user.host == null ? user.username : `${user.username}@${user.host}`;
|
||||
};
|
||||
|
||||
export const parseAcct = (acct: string): Acct => {
|
||||
if (acct.startsWith('@')) acct = acct.substr(1);
|
||||
const split = acct.split('@', 2);
|
||||
return { username: split[0], host: split[1] || null };
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
import Acct from './type';
|
||||
|
||||
export default (acct: string): Acct => {
|
||||
if (acct.startsWith('@')) acct = acct.substr(1);
|
||||
const split = acct.split('@', 2);
|
||||
return { username: split[0], host: split[1] || null };
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
import Acct from './type';
|
||||
|
||||
export default (user: Acct) => {
|
||||
return user.host == null ? user.username : `${user.username}@${user.host}`;
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
type Acct = {
|
||||
username: string;
|
||||
host: string | null;
|
||||
};
|
||||
|
||||
export default Acct;
|
|
@ -2,9 +2,9 @@ import { Antenna } from '../models/entities/antenna';
|
|||
import { Note } from '../models/entities/note';
|
||||
import { User } from '../models/entities/user';
|
||||
import { UserListJoinings, UserGroupJoinings } from '../models';
|
||||
import parseAcct from './acct/parse';
|
||||
import { getFullApAccount } from './convert-host';
|
||||
import { PackedNote } from '../models/repositories/note';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
|
||||
/**
|
||||
* noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as Bull from 'bull';
|
|||
|
||||
import { queueLogger } from '../../logger';
|
||||
import follow from '../../../services/following/create';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { resolveUser } from '../../../remote/resolve-user';
|
||||
import { downloadTextFile } from '@/misc/download-text-file';
|
||||
import { isSelfHost, toPuny } from '@/misc/convert-host';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as Bull from 'bull';
|
||||
|
||||
import { queueLogger } from '../../logger';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { resolveUser } from '../../../remote/resolve-user';
|
||||
import { pushUserToUserList } from '../../../services/user-list/push';
|
||||
import { downloadTextFile } from '@/misc/download-text-file';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from '../define';
|
||||
import { Users } from '../../../models';
|
||||
import { fetchMeta } from '@/misc/fetch-meta';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { User } from '../../../models/entities/user';
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as Limiter from 'ratelimiter';
|
||||
import { redisClient } from '../../db/redis';
|
||||
import { IEndpoint } from './endpoints';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import { User } from '../../models/entities/user';
|
||||
import Logger from '../../services/logger';
|
||||
|
||||
|
|
|
@ -107,6 +107,13 @@
|
|||
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
|
||||
}
|
||||
|
||||
const customCss = localStorage.getItem('customCss');
|
||||
if (customCss && customCss.length > 0) {
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = customCss;
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-inner-declarations
|
||||
function renderError(code, details) {
|
||||
document.documentElement.innerHTML = `
|
||||
|
|
|
@ -18,7 +18,7 @@ import { fetchMeta } from '@/misc/fetch-meta';
|
|||
import { genOpenapiSpec } from '../api/openapi/gen-spec';
|
||||
import config from '@/config';
|
||||
import { Users, Notes, Emojis, UserProfiles, Pages, Channels, Clips, GalleryPosts } from '../../models';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { getNoteSummary } from '@/misc/get-note-summary';
|
||||
import { getConnection } from 'typeorm';
|
||||
import { redisClient } from '../../db/redis';
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import * as Router from '@koa/router';
|
||||
|
||||
import config from '@/config';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import Acct from '@/misc/acct/type';
|
||||
import { parseAcct, Acct } from '@/misc/acct';
|
||||
import { links } from './nodeinfo';
|
||||
import { escapeAttribute, escapeValue } from '../prelude/xml';
|
||||
import { Users } from '../models';
|
||||
|
|
|
@ -3,15 +3,17 @@ import { User } from '../models/entities/user';
|
|||
import { sendEmail } from './send-email';
|
||||
import * as locales from '../../locales/';
|
||||
import { I18n } from '@/misc/i18n';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
|
||||
// TODO: locale ファイルをクライアント用とサーバー用で分けたい
|
||||
|
||||
async function follow(userId: User['id'], args: {}) {
|
||||
async function follow(userId: User['id'], follower: User) {
|
||||
const userProfile = await UserProfiles.findOneOrFail({ userId: userId });
|
||||
if (!userProfile.email || !userProfile.emailNotificationTypes.includes('follow')) return;
|
||||
const locale = locales[userProfile.lang || 'ja-JP'];
|
||||
const i18n = new I18n(locale);
|
||||
sendEmail(userProfile.email, i18n.t('_email._follow.title'), 'test', 'test');
|
||||
// TODO: render user information html
|
||||
sendEmail(userProfile.email, i18n.t('_email._follow.title'), `${follower.name} (@${getAcct(follower)})`, `${follower.name} (@${getAcct(follower)})`);
|
||||
}
|
||||
|
||||
async function receiveFollowRequest(userId: User['id'], args: {}) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { initDb } from '@/db/postgre';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
|
||||
async function main(acct: string): Promise<any> {
|
||||
await initDb();
|
||||
|
|
Loading…
Reference in a new issue