Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
31de530497 | |||
16b6b1f2b3 | |||
a2a25eb5f8 | |||
274cf1af1c | |||
7d11c8b767 | |||
7e50e03cfb |
12
README.md
12
README.md
@ -73,17 +73,17 @@ Please see [Contribution guide](./CONTRIBUTING.md).
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D" alt="negao"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1?token-time=2145916800&token-hash=d6P5MWHHsCMxUuBAEPAoVc5wLUR19mIhqAq7Ma9h9rI%3D" alt="ne_moni"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/1?token-time=2145916800&token-hash=f03BFb4S2FUx9YEt87TnEmifb4h33OywGBW2akQVtQY%3D" alt="Melilot"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/2?token-time=2145916800&token-hash=rwZ8qvbm_kpA4ib3kc07tVKupXeySpY5ATQFGxfL9v0%3D" alt="Axella"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/2?token-time=2145916800&token-hash=mgPdX9TqZxEg4TTPuc477dxhIgYk9246qafjWZEqZ7g%3D" alt="Melilot"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/2?token-time=2145916800&token-hash=rwZ8qvbm_kpA4ib3kc07tVKupXeySpY5ATQFGxfL9v0%3D" alt="Xeltica"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td>
|
||||
<td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=zwSu01tOtn5xTUucDZHuPsCxF2HBEMVs9ROJKTlEV_o%3D" alt="nemu"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=12731202">negao</a></td>
|
||||
<td><a href="https://www.patreon.com/negao">negao</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
||||
<td><a href="https://www.patreon.com/AxellaMC">Axella</a></td>
|
||||
<td><a href="https://www.patreon.com/AxellaMC">Xeltica</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=3384329">べすれい</a></td>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
|
||||
@ -91,19 +91,17 @@ Please see [Contribution guide](./CONTRIBUTING.md).
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/2?token-time=2145916800&token-hash=zElv7ZcPL3viGsXbNG_KWiKrbV0vvw1gk0panx8DJoo%3D" alt="Naoki Kosaka"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12931605/ead494101f364dffa90efe49e36fb494/1?token-time=2145916800&token-hash=NzSFPjIlodXyv41rwK61aZWVZWfI4surJaNj8vWKvqM%3D" alt="Reiju"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=UERBN4OyP7Nh5XwwdDg0N0IE5cD6_qUQMO81Z5Wizso%3D" alt="Hiratake"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D" alt="dansup"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D" alt="Takashi Shibuya"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12931605">Reiju</a></td>
|
||||
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
|
||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||
</tr></table>
|
||||
|
||||
**Last updated:** Sun, 02 Sep 2018 05:30:06 UTC
|
||||
**Last updated:** Tue, 02 Oct 2018 09:25:07 UTC
|
||||
<!-- PATREON_END -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
|
@ -311,6 +311,10 @@ common/views/components/theme.vue:
|
||||
uninstalled: "「{}」をアンインストールしました"
|
||||
author: "作者"
|
||||
desc: "説明"
|
||||
export: "エクスポート"
|
||||
import: "インポート"
|
||||
import-by-code: "またはコードをペースト"
|
||||
theme-name-required: "テーマ名は必須です。"
|
||||
|
||||
common/views/components/cw-button.vue:
|
||||
hide: "隠す"
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "9.1.0",
|
||||
"clientVersion": "1.0.10056",
|
||||
"version": "9.2.0",
|
||||
"clientVersion": "1.0.10062",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
|
@ -25,6 +25,9 @@
|
||||
<ui-input v-model="myThemeName">
|
||||
<span>%i18n:@theme-name%</span>
|
||||
</ui-input>
|
||||
<ui-textarea v-model="myThemeDesc">
|
||||
<span>%i18n:@desc%</span>
|
||||
</ui-textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div style="padding-bottom:8px;">%i18n:@primary-color%:</div>
|
||||
@ -44,10 +47,13 @@
|
||||
|
||||
<details>
|
||||
<summary>%fa:download% %i18n:@install-a-theme%</summary>
|
||||
<ui-button @click="import_()">%fa:file-import% %i18n:@import%</ui-button>
|
||||
<input ref="file" type="file" accept=".misskeytheme" style="display:none;" @change="onUpdateImportFile"/>
|
||||
<p>%i18n:@import-by-code%:</p>
|
||||
<ui-textarea v-model="installThemeCode">
|
||||
<span>%i18n:@theme-code%</span>
|
||||
</ui-textarea>
|
||||
<ui-button @click="install()">%fa:check% %i18n:@install%</ui-button>
|
||||
<ui-button @click="() => install(this.installThemeCode)">%fa:check% %i18n:@install%</ui-button>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@ -65,6 +71,7 @@
|
||||
<ui-textarea readonly :value="selectedInstalledThemeCode">
|
||||
<span>%i18n:@theme-code%</span>
|
||||
</ui-textarea>
|
||||
<ui-button @click="export_()" link :download="`${selectedInstalledTheme.name}.misskeytheme`" ref="export">%fa:box% %i18n:@export%</ui-button>
|
||||
<ui-button @click="uninstall()">%fa:trash-alt R% %i18n:@uninstall%</ui-button>
|
||||
</template>
|
||||
</details>
|
||||
@ -104,6 +111,7 @@ export default Vue.extend({
|
||||
selectedInstalledThemeId: null,
|
||||
myThemeBase: 'light',
|
||||
myThemeName: '',
|
||||
myThemeDesc: '',
|
||||
myThemePrimary: lightTheme.vars.primary,
|
||||
myThemeSecondary: lightTheme.vars.secondary,
|
||||
myThemeText: lightTheme.vars.text
|
||||
@ -143,6 +151,7 @@ export default Vue.extend({
|
||||
return {
|
||||
name: this.myThemeName,
|
||||
author: this.$store.state.i.username,
|
||||
desc: this.myThemeDesc,
|
||||
base: this.myThemeBase,
|
||||
vars: {
|
||||
primary: tinycolor(typeof this.myThemePrimary == 'string' ? this.myThemePrimary : this.myThemePrimary.rgba).toRgbString(),
|
||||
@ -177,11 +186,11 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
methods: {
|
||||
install() {
|
||||
install(code) {
|
||||
let theme;
|
||||
|
||||
try {
|
||||
theme = JSON5.parse(this.installThemeCode);
|
||||
theme = JSON5.parse(code);
|
||||
} catch (e) {
|
||||
alert('%i18n:@invalid-theme%');
|
||||
return;
|
||||
@ -219,12 +228,39 @@ export default Vue.extend({
|
||||
alert('%i18n:@uninstalled%'.replace('{}', theme.name));
|
||||
},
|
||||
|
||||
import_() {
|
||||
(this.$refs.file as any).click();
|
||||
}
|
||||
|
||||
export_() {
|
||||
const blob = new Blob([this.selectedInstalledThemeCode], {
|
||||
type: 'application/json5'
|
||||
});
|
||||
this.$refs.export.$el.href = window.URL.createObjectURL(blob);
|
||||
},
|
||||
|
||||
onUpdateImportFile() {
|
||||
const f = (this.$refs.file as any).files[0];
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = e => {
|
||||
this.install(e.target.result);
|
||||
};
|
||||
|
||||
reader.readAsText(f);
|
||||
},
|
||||
|
||||
preview() {
|
||||
applyTheme(this.myTheme, false);
|
||||
},
|
||||
|
||||
gen() {
|
||||
const theme = this.myTheme;
|
||||
if (theme.name == null || theme.name.trim() == '') {
|
||||
alert('%i18n:@theme-name-required%');
|
||||
return;
|
||||
}
|
||||
theme.id = uuid();
|
||||
const themes = this.$store.state.device.themes.concat(theme);
|
||||
this.$store.commit('device/set', {
|
||||
@ -239,10 +275,14 @@ export default Vue.extend({
|
||||
<style lang="stylus" scoped>
|
||||
.nicnklzforebnpfgasiypmpdaaglujqm
|
||||
> details
|
||||
margin-top 16px
|
||||
padding-top 16px
|
||||
border-top solid 1px var(--faceDivider)
|
||||
|
||||
> summary
|
||||
padding 16px 0
|
||||
|
||||
> *:last-child
|
||||
margin-bottom 16px
|
||||
|
||||
> .creator
|
||||
> div
|
||||
padding 16px 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<button class="dmtdnykelhudezerjlfpbhgovrgnqqgr" :class="[styl, { inline, primary }]" :type="type" @click="$emit('click')">
|
||||
<component class="dmtdnykelhudezerjlfpbhgovrgnqqgr" :is="link ? 'a' : 'button'" :class="[styl, { inline, primary }]" :type="type" @click="$emit('click')">
|
||||
<slot></slot>
|
||||
</button>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@ -21,6 +21,11 @@ export default Vue.extend({
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
link: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -35,15 +40,20 @@ export default Vue.extend({
|
||||
.dmtdnykelhudezerjlfpbhgovrgnqqgr
|
||||
display block
|
||||
width 100%
|
||||
min-height 40px
|
||||
margin 0
|
||||
padding 0
|
||||
padding 8px
|
||||
text-align center
|
||||
font-weight normal
|
||||
font-size 16px
|
||||
border none
|
||||
border-radius 6px
|
||||
outline none
|
||||
box-shadow none
|
||||
text-decoration none
|
||||
user-select none
|
||||
|
||||
*
|
||||
pointer-events none
|
||||
|
||||
&:focus
|
||||
&:after
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="qldxjjsrseehkusjuoooapmsprvfrxyl mk-admin-card">
|
||||
<header>%i18n:@announcements%</header>
|
||||
<textarea v-model="broadcasts"></textarea>
|
||||
<textarea v-model="broadcasts" placeholder='[ { "title": "Title1", "text": "Text1" }, { "title": "Title2", "text": "Text2" } ]'></textarea>
|
||||
<button class="ui" @click="save">%i18n:@save%</button>
|
||||
</div>
|
||||
</template>
|
||||
@ -22,8 +22,21 @@ export default Vue.extend({
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
let json;
|
||||
|
||||
try {
|
||||
json = JSON.parse(this.broadcasts);
|
||||
} catch (e) {
|
||||
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
|
||||
return;
|
||||
}
|
||||
|
||||
(this as any).api('admin/update-meta', {
|
||||
broadcasts: JSON.parse(this.broadcasts)
|
||||
broadcasts: json
|
||||
}).then(() => {
|
||||
(this as any).os.apis.dialog({ text: `Saved` });
|
||||
}.catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed ${e}` });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
<x-cpu-memory :connection="connection"/>
|
||||
</div>
|
||||
|
||||
<div class="form">
|
||||
<div v-if="this.$store.state.i && this.$store.state.i.isAdmin" class="form">
|
||||
<div>
|
||||
<label>
|
||||
<p>%i18n:@banner-url%</p>
|
||||
@ -81,6 +81,8 @@ export default Vue.extend({
|
||||
invite() {
|
||||
(this as any).api('admin/invite').then(x => {
|
||||
this.inviteCode = x.code;
|
||||
}).catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed ${e}` });
|
||||
});
|
||||
},
|
||||
updateMeta() {
|
||||
@ -88,6 +90,10 @@ export default Vue.extend({
|
||||
disableRegistration: this.disableRegistration,
|
||||
disableLocalTimeline: this.disableLocalTimeline,
|
||||
bannerUrl: this.bannerUrl
|
||||
}).then(() => {
|
||||
(this as any).os.apis.dialog({ text: `Saved` });
|
||||
}).catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed ${e}` });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,10 @@ export default Vue.extend({
|
||||
save() {
|
||||
(this as any).api('admin/update-meta', {
|
||||
hidedTags: this.hidedTags.split('\n')
|
||||
}).then(() => {
|
||||
(this as any).os.apis.dialog({ text: `Saved` });
|
||||
}).catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed ${e}` });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -21,18 +21,24 @@ export default Vue.extend({
|
||||
async suspendUser() {
|
||||
this.suspending = true;
|
||||
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
const process = async () => {
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
|
||||
await (this as any).os.api("admin/suspend-user", {
|
||||
userId: user.id
|
||||
await (this as any).os.api("admin/suspend-user", {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@suspended%" });
|
||||
};
|
||||
|
||||
await process().catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
|
||||
});
|
||||
|
||||
this.suspending = false;
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@suspended%" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -21,18 +21,25 @@ export default Vue.extend({
|
||||
async unsuspendUser() {
|
||||
this.unsuspending = true;
|
||||
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
const process = async () => {
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
|
||||
await (this as any).os.api("admin/unsuspend-user", {
|
||||
userId: user.id
|
||||
await (this as any).os.api("admin/unsuspend-user", {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@unsuspended%" });
|
||||
};
|
||||
|
||||
await process().catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
|
||||
});
|
||||
|
||||
this.unsuspending = false;
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@unsuspended%" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -21,18 +21,24 @@ export default Vue.extend({
|
||||
async unverifyUser() {
|
||||
this.unverifying = true;
|
||||
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
const process = async () => {
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
|
||||
await (this as any).os.api("admin/unverify-user", {
|
||||
userId: user.id
|
||||
await (this as any).os.api("admin/unverify-user", {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@unverified%" });
|
||||
};
|
||||
|
||||
await process().catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
|
||||
});
|
||||
|
||||
this.unverifying = false;
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@unverified%" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -21,18 +21,24 @@ export default Vue.extend({
|
||||
async verifyUser() {
|
||||
this.verifying = true;
|
||||
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
const process = async () => {
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
|
||||
await (this as any).os.api("admin/verify-user", {
|
||||
userId: user.id
|
||||
await (this as any).os.api("admin/verify-user", {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@verified%" });
|
||||
};
|
||||
|
||||
await process().catch(e => {
|
||||
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
|
||||
});
|
||||
|
||||
this.verifying = false;
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@verified%" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -3,9 +3,15 @@
|
||||
<nav>
|
||||
<ul>
|
||||
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
|
||||
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
|
||||
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
|
||||
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
|
||||
|
||||
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
|
||||
@click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
|
||||
|
||||
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
|
||||
@click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
|
||||
|
||||
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
|
||||
@click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
|
||||
|
||||
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
|
||||
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
|
||||
|
Reference in New Issue
Block a user