Merge branch 'develop'
This commit is contained in:
		
						commit
						449dc17df8
					
				
					 276 changed files with 3193 additions and 3095 deletions
				
			
		
							
								
								
									
										5
									
								
								.github/ISSUE_TEMPLATE/01_bug-report.md
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/ISSUE_TEMPLATE/01_bug-report.md
									
										
									
									
										vendored
									
									
								
							|  | @ -7,6 +7,11 @@ assignees: '' | |||
| 
 | ||||
| --- | ||||
| 
 | ||||
| <!-- | ||||
| Thanks for reporting! | ||||
| First, in order to avoid duplicate Issues, please search to see if the problem you found has already been reported. | ||||
| --> | ||||
| 
 | ||||
| ## 💡 Summary | ||||
| 
 | ||||
| <!-- Tell us what the bug is --> | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| see [releases](https://github.com/syuilo/misskey/releases) | ||||
| see [releases](https://github.com/misskey-dev/misskey/releases) | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
|   - 温度感高めで見てほしいものは責付いてください。 | ||||
| 
 | ||||
| ## Issues | ||||
| Feature suggestions and bug reports are filed in https://github.com/syuilo/misskey/issues . | ||||
| Feature suggestions and bug reports are filed in https://github.com/misskey-dev/misskey/issues . | ||||
| 
 | ||||
| * Please search existing issues to avoid duplication. If your issue is already filed, please add your reaction or comment to the existing one. | ||||
| * If you have multiple independent issues, please submit them separately. | ||||
|  |  | |||
							
								
								
									
										11
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
										
									
									
									
								
							|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| <div align="center"> | ||||
| 
 | ||||
| [](https://circleci.com/gh/syuilo/misskey) | ||||
| [](https://david-dm.org/syuilo/misskey) | ||||
| [](https://circleci.com/gh/misskey-dev/misskey) | ||||
| [](https://david-dm.org/misskey-dev/misskey) | ||||
| [](http://makeapullrequest.com) | ||||
| [](https://github.com/humanetech-community/awesome-humane-tech) | ||||
| 
 | ||||
|  | @ -22,11 +22,16 @@ Why don't you take a short break from the hustle and bustle of the city, and div | |||
| 
 | ||||
| --- | ||||
| 
 | ||||
| Do you have a question? Or are you experiencing trouble? | ||||
| Visit [our forum](https://forum.misskey.io/)! | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| :sparkles: Features | ||||
| ---------------------------------------------------------------- | ||||
| <a href="https://xn--931a.moe/"><img src="https://github.com/syuilo/misskey/blob/develop/assets/ai-orig.png?raw=true" align="right" height="320px"/></a> | ||||
| <a href="https://xn--931a.moe/"><img src="https://github.com/misskey-dev/misskey/blob/develop/assets/ai-orig.png?raw=true" align="right" height="320px"/></a> | ||||
| 
 | ||||
| <h3>Posting</h3> | ||||
| <p> | ||||
|  |  | |||
|  | @ -12,13 +12,13 @@ This guide describes how to install and setup Misskey with Docker. | |||
| ---------------------------------------------------------------- | ||||
| 1. Clone Misskey repository's master branch. | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 2. Move to misskey directory. | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 3. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag. | ||||
| 3. Checkout to the [latest release](https://github.com/misskey-dev/misskey/releases/latest) tag. | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,13 +13,13 @@ Ce guide explique comment installer et configurer Misskey avec Docker. | |||
| ---------------------------------------------------------------- | ||||
| 1. Clone le dépôt de Misskey sur la branche master. | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 2. Naviguez dans le dossier du dépôt. | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 3. Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest). | ||||
| 3. Checkout sur le tag de la [dernière version](https://github.com/misskey-dev/misskey/releases/latest). | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,13 +12,13 @@ Dockerを使ったMisskey構築方法 | |||
| ---------------------------------------------------------------- | ||||
| 1. masterブランチからMisskeyレポジトリをクローン | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 2. misskeyディレクトリに移動 | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 3. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認 | ||||
| 3. [最新のリリース](https://github.com/misskey-dev/misskey/releases/latest)を確認 | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,13 +12,13 @@ Docker 部署指南 | |||
| ---------------------------------------------------------------- | ||||
| 1. 克隆 Misskey 项目的 master 分支。 | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 2. 进入 misskey 文件夹。 | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 3. 检查 [最新发布版](https://github.com/syuilo/misskey/releases/latest) 标签。 | ||||
| 3. 检查 [最新发布版](https://github.com/misskey-dev/misskey/releases/latest) 标签。 | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,13 +40,13 @@ Please install and setup these softwares: | |||
| 
 | ||||
| 2. Clone the misskey repo from master branch. | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 3. Navigate to misskey directory | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 4. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) | ||||
| 4. Checkout to the [latest release](https://github.com/misskey-dev/misskey/releases/latest) | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,13 +41,13 @@ Installez les paquets suivants : | |||
| 
 | ||||
| 2. Clonez la branche master du dépôt misskey. | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 3. Accédez au dossier misskey. | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 4. Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest) | ||||
| 4. Checkout sur le tag de la [version la plus récente](https://github.com/misskey-dev/misskey/releases/latest) | ||||
| 
 | ||||
| 	`git checkout master` | ||||
|   | ||||
|  |  | |||
|  | @ -42,13 +42,13 @@ adduser --disabled-password --disabled-login misskey | |||
| 
 | ||||
| 2. masterブランチからMisskeyレポジトリをクローン | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 3. misskeyディレクトリに移動 | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 4. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認 | ||||
| 4. [最新のリリース](https://github.com/misskey-dev/misskey/releases/latest)を確認 | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,13 +40,13 @@ adduser --disabled-password --disabled-login misskey | |||
| 
 | ||||
| 2. 克隆 Misskey 项目的 master 分支。 | ||||
| 
 | ||||
| 	`git clone -b master git://github.com/syuilo/misskey.git` | ||||
| 	`git clone -b master git://github.com/misskey-dev/misskey.git` | ||||
| 
 | ||||
| 3. 进入 misskey 文件夹。 | ||||
| 
 | ||||
| 	`cd misskey` | ||||
| 
 | ||||
| 4. 检查 [最新发布版](https://github.com/syuilo/misskey/releases/latest) 标签。 | ||||
| 4. 检查 [最新发布版](https://github.com/misskey-dev/misskey/releases/latest) 标签。 | ||||
| 
 | ||||
| 	`git checkout master` | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # **DO NOT edit locale files** except `ja-JP.yml`. | ||||
| 
 | ||||
| When you add text to the ja-JP file (of syuilo/misskey), it will automatically be applied to other language files. | ||||
| When you add text to the ja-JP file (of misskey-dev/misskey), it will automatically be applied to other language files. | ||||
| Translations added in ja-JP file should contain the original Japanese strings. | ||||
| 
 | ||||
| Please see [Contribution guide](../CONTRIBUTING.md) for more information. | ||||
|  |  | |||
|  | @ -687,6 +687,7 @@ textColor: "文字" | |||
| saveAs: "名前を付けて保存" | ||||
| advanced: "高度" | ||||
| value: "値" | ||||
| createdAt: "作成日時" | ||||
| updatedAt: "更新日時" | ||||
| saveConfirm: "保存しますか?" | ||||
| deleteConfirm: "削除しますか?" | ||||
|  | @ -710,6 +711,12 @@ typingUsers: "{users}が入力中" | |||
| jumpToSpecifiedDate: "特定の日付にジャンプ" | ||||
| showingPastTimeline: "過去のタイムラインを表示しています" | ||||
| clear: "クリア" | ||||
| markAllAsRead: "全て既読にする" | ||||
| goBack: "戻る" | ||||
| unlikeConfirm: "いいね解除しますか?" | ||||
| fullView: "フルビュー" | ||||
| quitFullView: "フルビュー解除" | ||||
| addDescription: "説明を追加" | ||||
| 
 | ||||
| _email: | ||||
|   _follow: | ||||
|  | @ -878,6 +885,7 @@ _theme: | |||
|   install: "テーマのインストール" | ||||
|   manage: "テーマの管理" | ||||
|   code: "テーマコード" | ||||
|   description: "説明" | ||||
|   installed: "{name}をインストールしました" | ||||
|   installedThemes: "インストールされたテーマ" | ||||
|   builtinThemes: "標準のテーマ" | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ export class AddSomeUrls1557761316509 implements MigrationInterface { | |||
| 
 | ||||
|     public async up(queryRunner: QueryRunner): Promise<any> { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://github.com/syuilo/misskey'`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://github.com/syuilo/misskey/issues/new'`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://github.com/misskey-dev/misskey'`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://github.com/misskey-dev/misskey/issues/new'`); | ||||
|     } | ||||
| 
 | ||||
|     public async down(queryRunner: QueryRunner): Promise<any> { | ||||
|  |  | |||
							
								
								
									
										12
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
										
									
									
									
								
							|  | @ -1,11 +1,11 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"author": "syuilo <syuilotan@yahoo.co.jp>", | ||||
| 	"version": "12.75.1", | ||||
| 	"version": "12.76.0", | ||||
| 	"codename": "indigo", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
| 		"url": "https://github.com/syuilo/misskey.git" | ||||
| 		"url": "https://github.com/misskey-dev/misskey.git" | ||||
| 	}, | ||||
| 	"main": "./index.js", | ||||
| 	"private": true, | ||||
|  | @ -88,6 +88,7 @@ | |||
| 		"@types/parsimmon": "1.10.6", | ||||
| 		"@types/portscanner": "2.1.0", | ||||
| 		"@types/pug": "2.0.4", | ||||
| 		"@types/punycode": "2.1.0", | ||||
| 		"@types/qrcode": "1.4.0", | ||||
| 		"@types/random-seed": "0.3.3", | ||||
| 		"@types/ratelimiter": "3.4.1", | ||||
|  | @ -109,7 +110,7 @@ | |||
| 		"@types/websocket": "1.0.2", | ||||
| 		"@types/ws": "7.4.0", | ||||
| 		"@typescript-eslint/parser": "4.18.0", | ||||
| 		"@vue/compiler-sfc": "3.0.7", | ||||
| 		"@vue/compiler-sfc": "3.0.8", | ||||
| 		"abort-controller": "3.0.0", | ||||
| 		"apexcharts": "3.26.0", | ||||
| 		"autobind-decorator": "2.4.0", | ||||
|  | @ -180,6 +181,7 @@ | |||
| 		"markdown-it": "12.0.4", | ||||
| 		"markdown-it-anchor": "7.1.0", | ||||
| 		"matter-js": "0.16.1", | ||||
| 		"mfm-js": "0.14.0", | ||||
| 		"mocha": "8.3.2", | ||||
| 		"moji": "0.5.1", | ||||
| 		"ms": "2.1.3", | ||||
|  | @ -190,7 +192,6 @@ | |||
| 		"object-assign-deep": "0.4.0", | ||||
| 		"os-utils": "0.0.14", | ||||
| 		"parse5": "6.0.1", | ||||
| 		"parsimmon": "1.16.0", | ||||
| 		"pg": "8.5.1", | ||||
| 		"portscanner": "2.2.0", | ||||
| 		"postcss": "8.2.8", | ||||
|  | @ -245,13 +246,14 @@ | |||
| 		"uuid": "8.3.2", | ||||
| 		"v-debounce": "0.1.2", | ||||
| 		"vanilla-tilt": "1.7.0", | ||||
| 		"vue": "3.0.7", | ||||
| 		"vue": "3.0.8", | ||||
| 		"vue-color": "2.8.1", | ||||
| 		"vue-json-pretty": "1.7.1", | ||||
| 		"vue-loader": "16.1.2", | ||||
| 		"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.27.2", | ||||
|  |  | |||
|  | @ -8,19 +8,15 @@ | |||
| 			</template> | ||||
| 		</I18n> | ||||
| 	</template> | ||||
| 	<div class="dpvffvvy"> | ||||
| 	<div class="dpvffvvy _monolithic_"> | ||||
| 		<div class="_section"> | ||||
| 			<div class="_content"> | ||||
| 				<MkTextarea v-model:value="comment"> | ||||
| 					<span>{{ $ts.details }}</span> | ||||
| 					<template #desc>{{ $ts.fillAbuseReportDescription }}</template> | ||||
| 				</MkTextarea> | ||||
| 			</div> | ||||
| 			<MkTextarea v-model:value="comment"> | ||||
| 				<span>{{ $ts.details }}</span> | ||||
| 				<template #desc>{{ $ts.fillAbuseReportDescription }}</template> | ||||
| 			</MkTextarea> | ||||
| 		</div> | ||||
| 		<div class="_section"> | ||||
| 			<div class="_content"> | ||||
| 				<MkButton @click="send" primary full :disabled="comment.length === 0">{{ $ts.send }}</MkButton> | ||||
| 			</div> | ||||
| 			<MkButton @click="send" primary full :disabled="comment.length === 0">{{ $ts.send }}</MkButton> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </XWindow> | ||||
|  | @ -80,6 +76,6 @@ export default defineComponent({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .dpvffvvy { | ||||
| 	--section-padding: 16px; | ||||
| 	--root-margin: 16px; | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	> footer { | ||||
| 		padding: 12px 16px; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 		> span { | ||||
| 			opacity: 0.7; | ||||
|  |  | |||
|  | @ -37,14 +37,16 @@ export default defineComponent({ | |||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		const noGap = [...document.querySelectorAll('._noGap_')].some(el => el.contains(this.$parent.$el)); | ||||
| 
 | ||||
| 		return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? { | ||||
| 			class: 'sqadhkmv _list_', | ||||
| 			class: 'sqadhkmv' + (noGap ? ' _block' : ''), | ||||
| 			name: 'list', | ||||
| 			tag: 'div', | ||||
| 			'data-direction': this.direction, | ||||
| 			'data-reversed': this.reversed ? 'true' : 'false', | ||||
| 		} : { | ||||
| 			class: 'sqadhkmv _list_', | ||||
| 			class: 'sqadhkmv', | ||||
| 		}, this.items.map((item, i) => { | ||||
| 			const el = this.$slots.default({ | ||||
| 				item: item | ||||
|  | @ -117,11 +119,7 @@ export default defineComponent({ | |||
| 			transform: translateY(-64px); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
| .sqadhkmv { | ||||
| 	> .separator { | ||||
| 		text-align: center; | ||||
| 
 | ||||
|  | @ -155,4 +153,25 @@ export default defineComponent({ | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._noGap_ .sqadhkmv { | ||||
| 	> * { | ||||
| 		margin: 0 !important; | ||||
| 		border: none; | ||||
| 		border-radius: 0; | ||||
| 		box-shadow: none; | ||||
| 
 | ||||
| 		&:not(:last-child) { | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._inContainer_ .sqadhkmv > * { | ||||
| 	margin: 0 !important; | ||||
| 	border: none; | ||||
| 	border-bottom: solid 0.5px var(--divider); | ||||
| 	border-radius: 0; | ||||
| 	box-shadow: none; | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -330,8 +330,8 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> .thumbnail { | ||||
| 		width: 128px; | ||||
| 		height: 128px; | ||||
| 		width: 110px; | ||||
| 		height: 110px; | ||||
| 		margin: auto; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| 			<span class="folder current" v-if="folder != null">{{ folder.name }}</span> | ||||
| 		</div> | ||||
| 	</nav> | ||||
| 	<div class="main _section" :class="{ uploading: uploadings.length > 0, fetching }" | ||||
| 	<div class="main" :class="{ uploading: uploadings.length > 0, fetching }" | ||||
| 		ref="main" | ||||
| 		@dragover.prevent.stop="onDragover" | ||||
| 		@dragenter="onDragenter" | ||||
|  | @ -704,6 +704,7 @@ export default defineComponent({ | |||
| 	> .main { | ||||
| 		flex: 1; | ||||
| 		overflow: auto; | ||||
| 		padding: var(--margin); | ||||
| 
 | ||||
| 		&, * { | ||||
| 			user-select: none; | ||||
|  | @ -735,7 +736,7 @@ export default defineComponent({ | |||
| 				> .folder, | ||||
| 				> .file { | ||||
| 					flex-grow: 1; | ||||
| 					width: 144px; | ||||
| 					width: 128px; | ||||
| 					margin: 4px; | ||||
| 					box-sizing: border-box; | ||||
| 				} | ||||
|  | @ -743,7 +744,7 @@ export default defineComponent({ | |||
| 				> .padding { | ||||
| 					flex-grow: 1; | ||||
| 					pointer-events: none; | ||||
| 					width: 144px + 8px; | ||||
| 					width: 128px + 8px; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ export default defineComponent({ | |||
| 		> .index { | ||||
| 			min-height: var(--height); | ||||
| 			position: relative; | ||||
| 			border-bottom: solid 1px var(--divider); | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 				 | ||||
| 			> .arrow { | ||||
| 				position: absolute; | ||||
|  | @ -181,7 +181,7 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			&.result { | ||||
| 				border-bottom: solid 1px var(--divider); | ||||
| 				border-bottom: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 				&:empty { | ||||
| 					display: none; | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ export default defineComponent({ | |||
| 		> .index { | ||||
| 			min-height: var(--height); | ||||
| 			position: relative; | ||||
| 			border-bottom: solid 1px var(--divider); | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 				 | ||||
| 			> .arrow { | ||||
| 				position: absolute; | ||||
|  | @ -177,7 +177,7 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			&.result { | ||||
| 				border-bottom: solid 1px var(--divider); | ||||
| 				border-bottom: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 				&:empty { | ||||
| 					display: none; | ||||
|  |  | |||
|  | @ -402,7 +402,7 @@ export default defineComponent({ | |||
| 		> .tab { | ||||
| 			flex: 1; | ||||
| 			height: 38px; | ||||
| 			border-top: solid 1px var(--divider); | ||||
| 			border-top: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 			&.active { | ||||
| 				border-top: solid 1px var(--accent); | ||||
|  | @ -425,7 +425,7 @@ export default defineComponent({ | |||
| 		> div { | ||||
| 			&:not(.index) { | ||||
| 				padding: 4px 0 8px 0; | ||||
| 				border-top: solid 1px var(--divider); | ||||
| 				border-top: solid 0.5px var(--divider); | ||||
| 			} | ||||
| 
 | ||||
| 			> header { | ||||
|  | @ -492,7 +492,7 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			&.result { | ||||
| 				border-bottom: solid 1px var(--divider); | ||||
| 				border-bottom: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 				&:empty { | ||||
| 					display: none; | ||||
|  |  | |||
|  | @ -20,12 +20,16 @@ export default defineComponent({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .rbusrurv { | ||||
| 	line-height: 1.4em; | ||||
| 	// 他のCSSからも参照されるので消さないように | ||||
| 	--formXPadding: 32px; | ||||
| 	--formYPadding: 32px; | ||||
| 
 | ||||
| 	line-height: 1.3em; | ||||
| 	background: var(--bg); | ||||
| 	padding: 32px; | ||||
| 	padding: var(--formYPadding) var(--formXPadding); | ||||
| 
 | ||||
| 	&:not(.wide).max-width_400px { | ||||
| 		padding: 32px 0; | ||||
| 		--formXPadding: 0px; | ||||
| 
 | ||||
| 		> ::v-deep(*) { | ||||
| 			._formPanel { | ||||
|  |  | |||
|  | @ -1,32 +1,48 @@ | |||
| ._formPanel { | ||||
| 	background: var(--panel); | ||||
| 	border-radius: var(--radius); | ||||
| 	transition: background 0.2s ease; | ||||
| 
 | ||||
| 	&._formClickable { | ||||
| 		&:hover { | ||||
| 			//background: var(--panelHighlight); | ||||
| 		} | ||||
| 
 | ||||
| 		&:active { | ||||
| 			background: var(--panelHighlight); | ||||
| 			transition: background 0s; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._formLabel, | ||||
| ._formCaption { | ||||
| 	font-size: 80%; | ||||
| 	color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 	&:empty { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._formLabel { | ||||
| 	font-size: 80%; | ||||
| 	padding: 0 16px 8px 16px; | ||||
| 	opacity: 0.8; | ||||
| 	position: sticky; | ||||
| 	top: var(--stickyTop, 0px); | ||||
| 	z-index: 2; | ||||
| 	margin: -8px calc(var(--formXPadding) * -1) 0 calc(var(--formXPadding) * -1); | ||||
| 	padding: 8px calc(16px + var(--formXPadding)) 8px calc(16px + var(--formXPadding)); | ||||
| 	background: var(--X17); | ||||
| 	-webkit-backdrop-filter: blur(10px); | ||||
| 	backdrop-filter: blur(10px); | ||||
| } | ||||
| 
 | ||||
| 	&:empty { | ||||
| 		display: none; | ||||
| 	} | ||||
| ._themeChanging_ ._formLabel { | ||||
| 	transition: none !important; | ||||
| 	background: transparent; | ||||
| } | ||||
| 
 | ||||
| ._formCaption { | ||||
| 	font-size: 80%; | ||||
| 	padding: 8px 16px 0 16px; | ||||
| 	opacity: 0.8; | ||||
| 
 | ||||
| 	&:empty { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._formItem { | ||||
|  |  | |||
							
								
								
									
										49
									
								
								src/client/components/form/info.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/client/components/form/info.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| <template> | ||||
| <div class="fzenkabp _formItem"> | ||||
| 	<div class="_formPanel" :class="{ warn }"> | ||||
| 		<i v-if="warn"><Fa :icon="faExclamationTriangle"/></i> | ||||
| 		<i v-else><Fa :icon="faInfoCircle"/></i> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		warn: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faInfoCircle, faExclamationTriangle | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .fzenkabp { | ||||
| 	> div { | ||||
| 		padding: 14px 16px; | ||||
| 		font-size: 90%; | ||||
| 		background: var(--infoBg); | ||||
| 		color: var(--infoFg); | ||||
| 
 | ||||
| 		&.warn { | ||||
| 			background: var(--infoWarnBg); | ||||
| 			color: var(--infoWarnFg); | ||||
| 		} | ||||
| 
 | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -215,7 +215,7 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		$height: 52px; | ||||
| 		$height: 48px; | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> input { | ||||
|  |  | |||
|  | @ -66,6 +66,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 		&.active { | ||||
| 			color: var(--accent); | ||||
| 			background: var(--panelHighlight); | ||||
| 		} | ||||
| 
 | ||||
| 		> .icon { | ||||
|  |  | |||
|  | @ -69,8 +69,8 @@ export default defineComponent({ | |||
| 			display: inline-block; | ||||
| 			vertical-align: bottom; | ||||
| 			position: relative; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			width: 16px; | ||||
| 			height: 16px; | ||||
| 			margin-right: 8px; | ||||
| 			background: none; | ||||
| 			border: 2px solid var(--inputBorder); | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ export default defineComponent({ | |||
| 	position: relative; | ||||
| 
 | ||||
| 	> .main { | ||||
| 		padding: 24px 16px; | ||||
| 		padding: 22px 16px; | ||||
| 
 | ||||
| 		> input { | ||||
| 			display: block; | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ export default defineComponent({ | |||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			height: 52px; | ||||
| 			height: 48px; | ||||
| 			background: none; | ||||
| 			border: none; | ||||
| 			border-radius: 0; | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ export default defineComponent({ | |||
| 	> .main { | ||||
| 		position: relative; | ||||
| 		display: flex; | ||||
| 		padding: 16px; | ||||
| 		padding: 14px 16px; | ||||
| 		cursor: pointer; | ||||
| 
 | ||||
| 		> * { | ||||
|  |  | |||
|  | @ -93,6 +93,10 @@ export default defineComponent({ | |||
| 			os.pageWindow(this.to); | ||||
| 		}, | ||||
| 
 | ||||
| 		modalWindow() { | ||||
| 			os.modalPageWindow(this.to); | ||||
| 		}, | ||||
| 
 | ||||
| 		popout() { | ||||
| 			popout(this.to); | ||||
| 		}, | ||||
|  | @ -111,6 +115,8 @@ export default defineComponent({ | |||
| 			if (this.behavior) { | ||||
| 				if (this.behavior === 'window') { | ||||
| 					return this.window(); | ||||
| 				} else if (this.behavior === 'modalWindow') { | ||||
| 					return this.modalWindow(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <span class="mk-acct" v-once> | ||||
| <span class="mk-acct"> | ||||
| 	<span class="name">@{{ user.username }}</span> | ||||
| 	<span class="host" v-if="user.host || detail || $store.state.showFullAcct">@{{ user.host || host }}</span> | ||||
| </span> | ||||
|  | @ -7,11 +7,20 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { host } from '@client/config'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: ['user', 'detail'], | ||||
| 	props: { | ||||
| 		user: { | ||||
| 			type: Object, | ||||
| 			required: true | ||||
| 		}, | ||||
| 		detail: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			host: toUnicode(host), | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { toUnicode as decodePunycode } from 'punycode'; | ||||
| import { toUnicode as decodePunycode } from 'punycode/'; | ||||
| import { url as local } from '@client/config'; | ||||
| import { isDeviceTouch } from '@client/scripts/is-device-touch'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ export default defineComponent({ | |||
| 	> .sub { | ||||
| 		margin-top: 8px; | ||||
| 		padding-top: 8px; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ export default defineComponent({ | |||
| 
 | ||||
| .gqnyydlz { | ||||
| 	position: relative; | ||||
| 	border: solid 1px var(--divider); | ||||
| 	border: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 	> i { | ||||
| 		display: block; | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { host as localHost } from '@client/config'; | ||||
| import { wellKnownServices } from '../../well-known-services'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| import { VNode, defineComponent, h } from 'vue'; | ||||
| import { MfmForest } from '@client/../mfm/prelude'; | ||||
| import { parse, parsePlain } from '@client/../mfm/parse'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import MkUrl from '@client/components/global/url.vue'; | ||||
| import MkLink from '@client/components/link.vue'; | ||||
| import MkMention from '@client/components/mention.vue'; | ||||
|  | @ -46,17 +45,17 @@ export default defineComponent({ | |||
| 	render() { | ||||
| 		if (this.text == null || this.text == '') return; | ||||
| 
 | ||||
| 		const ast = (this.plain ? parsePlain : parse)(this.text); | ||||
| 		const ast = (this.plain ? mfm.parsePlain : mfm.parse)(this.text); | ||||
| 
 | ||||
| 		const validTime = (t: string | null | undefined) => { | ||||
| 			if (t == null) return null; | ||||
| 			return t.match(/^[0-9.]+s$/) ? t : null; | ||||
| 		}; | ||||
| 
 | ||||
| 		const genEl = (ast: MfmForest) => concat(ast.map((token): VNode[] => { | ||||
| 			switch (token.node.type) { | ||||
| 		const genEl = (ast: mfm.MfmNode[]) => concat(ast.map((token): VNode[] => { | ||||
| 			switch (token.type) { | ||||
| 				case 'text': { | ||||
| 					const text = token.node.props.text.replace(/(\r\n|\n|\r)/g, '\n'); | ||||
| 					const text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n'); | ||||
| 
 | ||||
| 					if (!this.plain) { | ||||
| 						const x = text.split('\n') | ||||
|  | @ -83,38 +82,38 @@ export default defineComponent({ | |||
| 				} | ||||
| 
 | ||||
| 				case 'fn': { | ||||
| 					// TODO: CSSを文字列で組み立てていくと token.node.props.args.~~~ 経由でCSSインジェクションできるのでよしなにやる
 | ||||
| 					// TODO: CSSを文字列で組み立てていくと token.props.args.~~~ 経由でCSSインジェクションできるのでよしなにやる
 | ||||
| 					let style; | ||||
| 					switch (token.node.props.name) { | ||||
| 					switch (token.props.name) { | ||||
| 						case 'tada': { | ||||
| 							style = `font-size: 150%;` + (this.$store.state.animatedMfm ? 'animation: tada 1s linear infinite both;' : ''); | ||||
| 							break; | ||||
| 						} | ||||
| 						case 'jelly': { | ||||
| 							const speed = validTime(token.node.props.args.speed) || '1s'; | ||||
| 							const speed = validTime(token.props.args.speed) || '1s'; | ||||
| 							style = (this.$store.state.animatedMfm ? `animation: mfm-rubberBand ${speed} linear infinite both;` : ''); | ||||
| 							break; | ||||
| 						} | ||||
| 						case 'twitch': { | ||||
| 							const speed = validTime(token.node.props.args.speed) || '0.5s'; | ||||
| 							const speed = validTime(token.props.args.speed) || '0.5s'; | ||||
| 							style = this.$store.state.animatedMfm ? `animation: mfm-twitch ${speed} ease infinite;` : ''; | ||||
| 							break; | ||||
| 						} | ||||
| 						case 'shake': { | ||||
| 							const speed = validTime(token.node.props.args.speed) || '0.5s'; | ||||
| 							const speed = validTime(token.props.args.speed) || '0.5s'; | ||||
| 							style = this.$store.state.animatedMfm ? `animation: mfm-shake ${speed} ease infinite;` : ''; | ||||
| 							break; | ||||
| 						} | ||||
| 						case 'spin': { | ||||
| 							const direction = | ||||
| 								token.node.props.args.left ? 'reverse' : | ||||
| 								token.node.props.args.alternate ? 'alternate' : | ||||
| 								token.props.args.left ? 'reverse' : | ||||
| 								token.props.args.alternate ? 'alternate' : | ||||
| 								'normal'; | ||||
| 							const anime = | ||||
| 								token.node.props.args.x ? 'mfm-spinX' : | ||||
| 								token.node.props.args.y ? 'mfm-spinY' : | ||||
| 								token.props.args.x ? 'mfm-spinX' : | ||||
| 								token.props.args.y ? 'mfm-spinY' : | ||||
| 								'mfm-spin'; | ||||
| 							const speed = validTime(token.node.props.args.speed) || '1.5s'; | ||||
| 							const speed = validTime(token.props.args.speed) || '1.5s'; | ||||
| 							style = this.$store.state.animatedMfm ? `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction};` : ''; | ||||
| 							break; | ||||
| 						} | ||||
|  | @ -128,8 +127,8 @@ export default defineComponent({ | |||
| 						} | ||||
| 						case 'flip': { | ||||
| 							const transform = | ||||
| 								(token.node.props.args.h && token.node.props.args.v) ? 'scale(-1, -1)' : | ||||
| 								token.node.props.args.v ? 'scaleY(-1)' : | ||||
| 								(token.props.args.h && token.props.args.v) ? 'scale(-1, -1)' : | ||||
| 								token.props.args.v ? 'scaleY(-1)' : | ||||
| 								'scaleX(-1)'; | ||||
| 							style = `transform: ${transform};`; | ||||
| 							break; | ||||
|  | @ -148,12 +147,12 @@ export default defineComponent({ | |||
| 						} | ||||
| 						case 'font': { | ||||
| 							const family = | ||||
| 								token.node.props.args.serif ? 'serif' : | ||||
| 								token.node.props.args.monospace ? 'monospace' : | ||||
| 								token.node.props.args.cursive ? 'cursive' : | ||||
| 								token.node.props.args.fantasy ? 'fantasy' : | ||||
| 								token.node.props.args.emoji ? 'emoji' : | ||||
| 								token.node.props.args.math ? 'math' : | ||||
| 								token.props.args.serif ? 'serif' : | ||||
| 								token.props.args.monospace ? 'monospace' : | ||||
| 								token.props.args.cursive ? 'cursive' : | ||||
| 								token.props.args.fantasy ? 'fantasy' : | ||||
| 								token.props.args.emoji ? 'emoji' : | ||||
| 								token.props.args.math ? 'math' : | ||||
| 								null; | ||||
| 							if (family) style = `font-family: ${family};`; | ||||
| 							break; | ||||
|  | @ -165,7 +164,7 @@ export default defineComponent({ | |||
| 						} | ||||
| 					} | ||||
| 					if (style == null) { | ||||
| 						return h('span', {}, ['[', token.node.props.name, ...genEl(token.children), ']']); | ||||
| 						return h('span', {}, ['[', token.props.name, ...genEl(token.children), ']']); | ||||
| 					} else { | ||||
| 						return h('span', { | ||||
| 							style: 'display: inline-block;' + style, | ||||
|  | @ -188,7 +187,7 @@ export default defineComponent({ | |||
| 				case 'url': { | ||||
| 					return [h(MkUrl, { | ||||
| 						key: Math.random(), | ||||
| 						url: token.node.props.url, | ||||
| 						url: token.props.url, | ||||
| 						rel: 'nofollow noopener', | ||||
| 					})]; | ||||
| 				} | ||||
|  | @ -196,7 +195,7 @@ export default defineComponent({ | |||
| 				case 'link': { | ||||
| 					return [h(MkLink, { | ||||
| 						key: Math.random(), | ||||
| 						url: token.node.props.url, | ||||
| 						url: token.props.url, | ||||
| 						rel: 'nofollow noopener', | ||||
| 					}, genEl(token.children))]; | ||||
| 				} | ||||
|  | @ -204,32 +203,31 @@ export default defineComponent({ | |||
| 				case 'mention': { | ||||
| 					return [h(MkMention, { | ||||
| 						key: Math.random(), | ||||
| 						host: (token.node.props.host == null && this.author && this.author.host != null ? this.author.host : token.node.props.host) || host, | ||||
| 						username: token.node.props.username | ||||
| 						host: (token.props.host == null && this.author && this.author.host != null ? this.author.host : token.props.host) || host, | ||||
| 						username: token.props.username | ||||
| 					})]; | ||||
| 				} | ||||
| 
 | ||||
| 				case 'hashtag': { | ||||
| 					return [h(MkA, { | ||||
| 						key: Math.random(), | ||||
| 						to: this.isNote ? `/tags/${encodeURIComponent(token.node.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.node.props.hashtag)}`, | ||||
| 						to: this.isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.props.hashtag)}`, | ||||
| 						style: 'color:var(--hashtag);' | ||||
| 					}, `#${token.node.props.hashtag}`)]; | ||||
| 					}, `#${token.props.hashtag}`)]; | ||||
| 				} | ||||
| 
 | ||||
| 				case 'blockCode': { | ||||
| 					return [h(MkCode, { | ||||
| 						key: Math.random(), | ||||
| 						code: token.node.props.code, | ||||
| 						lang: token.node.props.lang, | ||||
| 						code: token.props.code, | ||||
| 						lang: token.props.lang, | ||||
| 					})]; | ||||
| 				} | ||||
| 
 | ||||
| 				case 'inlineCode': { | ||||
| 					return [h(MkCode, { | ||||
| 						key: Math.random(), | ||||
| 						code: token.node.props.code, | ||||
| 						lang: token.node.props.lang, | ||||
| 						code: token.props.code, | ||||
| 						inline: true | ||||
| 					})]; | ||||
| 				} | ||||
|  | @ -246,10 +244,19 @@ export default defineComponent({ | |||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				case 'emoji': { | ||||
| 				case 'emojiCode': { | ||||
| 					return [h(MkEmoji, { | ||||
| 						key: Math.random(), | ||||
| 						emoji: token.node.props.name ? `:${token.node.props.name}:` : token.node.props.emoji, | ||||
| 						emoji: `:${token.props.name}:`, | ||||
| 						customEmojis: this.customEmojis, | ||||
| 						normal: this.plain | ||||
| 					})]; | ||||
| 				} | ||||
| 
 | ||||
| 				case 'unicodeEmoji': { | ||||
| 					return [h(MkEmoji, { | ||||
| 						key: Math.random(), | ||||
| 						emoji: token.props.emoji, | ||||
| 						customEmojis: this.customEmojis, | ||||
| 						normal: this.plain | ||||
| 					})]; | ||||
|  | @ -258,7 +265,7 @@ export default defineComponent({ | |||
| 				case 'mathInline': { | ||||
| 					return [h(MkFormula, { | ||||
| 						key: Math.random(), | ||||
| 						formula: token.node.props.formula, | ||||
| 						formula: token.props.formula, | ||||
| 						block: false | ||||
| 					})]; | ||||
| 				} | ||||
|  | @ -266,7 +273,7 @@ export default defineComponent({ | |||
| 				case 'mathBlock': { | ||||
| 					return [h(MkFormula, { | ||||
| 						key: Math.random(), | ||||
| 						formula: token.node.props.formula, | ||||
| 						formula: token.props.formula, | ||||
| 						block: true | ||||
| 					})]; | ||||
| 				} | ||||
|  | @ -274,12 +281,12 @@ export default defineComponent({ | |||
| 				case 'search': { | ||||
| 					return [h(MkGoogle, { | ||||
| 						key: Math.random(), | ||||
| 						q: token.node.props.query | ||||
| 						q: token.props.query | ||||
| 					})]; | ||||
| 				} | ||||
| 
 | ||||
| 				default: { | ||||
| 					console.error('unrecognized ast type:', token.node.type); | ||||
| 					console.error('unrecognized ast type:', token.type); | ||||
| 
 | ||||
| 					return []; | ||||
| 				} | ||||
|  |  | |||
							
								
								
									
										213
									
								
								src/client/components/modal-page-window.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/client/components/modal-page-window.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,213 @@ | |||
| <template> | ||||
| <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> | ||||
| 	<div class="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> | ||||
| 		<div class="header"> | ||||
| 			<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button> | ||||
| 			<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> | ||||
| 			<span class="title"> | ||||
| 				<XHeader :info="pageInfo" :with-back="false"/> | ||||
| 			</span> | ||||
| 			<button class="_button" @click="$refs.modal.close()"><Fa :icon="faTimes"/></button> | ||||
| 		</div> | ||||
| 		<div class="body _flat_"> | ||||
| 			<keep-alive> | ||||
| 				<component :is="component" v-bind="props" :ref="changePage"/> | ||||
| 			</keep-alive> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </MkModal> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkAlt, faExpandAlt, faLink, faChevronLeft, faColumns, faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| import XHeader from '@client/ui/_common_/header.vue'; | ||||
| import { popout } from '@client/scripts/popout'; | ||||
| import copyToClipboard from '@client/scripts/copy-to-clipboard'; | ||||
| import { resolve } from '@client/router'; | ||||
| import { url } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkModal, | ||||
| 		XHeader, | ||||
| 	}, | ||||
| 
 | ||||
| 	inject: { | ||||
| 		sideViewHook: { | ||||
| 			default: null | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	provide() { | ||||
| 		return { | ||||
| 			navHook: (path) => { | ||||
| 				this.navigate(path); | ||||
| 			} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		initialPath: { | ||||
| 			type: String, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		initialComponent: { | ||||
| 			type: Object, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		initialProps: { | ||||
| 			type: Object, | ||||
| 			required: false, | ||||
| 			default: () => {}, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['closed'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			width: 860, | ||||
| 			height: 660, | ||||
| 			pageInfo: null, | ||||
| 			path: this.initialPath, | ||||
| 			component: this.initialComponent, | ||||
| 			props: this.initialProps, | ||||
| 			history: [], | ||||
| 			faChevronLeft, faTimes, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		url(): string { | ||||
| 			return url + this.path; | ||||
| 		}, | ||||
| 
 | ||||
| 		contextmenu() { | ||||
| 			return [{ | ||||
| 				type: 'label', | ||||
| 				text: this.path, | ||||
| 			}, { | ||||
| 				icon: faExpandAlt, | ||||
| 				text: this.$ts.showInPage, | ||||
| 				action: this.expand | ||||
| 			}, this.sideViewHook ? { | ||||
| 				icon: faColumns, | ||||
| 				text: this.$ts.openInSideView, | ||||
| 				action: () => { | ||||
| 					this.sideViewHook(this.path); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			} : undefined, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				text: this.$ts.popout, | ||||
| 				action: this.popout | ||||
| 			}, null, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				text: this.$ts.openInNewTab, | ||||
| 				action: () => { | ||||
| 					window.open(this.url, '_blank'); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			}, { | ||||
| 				icon: faLink, | ||||
| 				text: this.$ts.copyLink, | ||||
| 				action: () => { | ||||
| 					copyToClipboard(this.url); | ||||
| 				} | ||||
| 			}]; | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		changePage(page) { | ||||
| 			if (page == null) return; | ||||
| 			if (page[symbols.PAGE_INFO]) { | ||||
| 				this.pageInfo = page[symbols.PAGE_INFO]; | ||||
| 			} | ||||
| 		}, | ||||
| 
 | ||||
| 		navigate(path, record = true) { | ||||
| 			if (record) this.history.push(this.path); | ||||
| 			this.path = path; | ||||
| 			const { component, props } = resolve(path); | ||||
| 			this.component = component; | ||||
| 			this.props = props; | ||||
| 		}, | ||||
| 
 | ||||
| 		back() { | ||||
| 			this.navigate(this.history.pop(), false); | ||||
| 		}, | ||||
| 
 | ||||
| 		expand() { | ||||
| 			this.$router.push(this.path); | ||||
| 			this.$refs.window.close(); | ||||
| 		}, | ||||
| 
 | ||||
| 		popout() { | ||||
| 			popout(this.path, this.$el); | ||||
| 			this.$refs.window.close(); | ||||
| 		}, | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .hrmcaedk { | ||||
| 	overflow: hidden; | ||||
| 	display: flex; | ||||
| 	flex-direction: column; | ||||
| 	contain: content; | ||||
| 
 | ||||
| 	--root-margin: 24px; | ||||
| 
 | ||||
| 	@media (max-width: 500px) { | ||||
| 		--root-margin: 16px; | ||||
| 	} | ||||
| 
 | ||||
| 	> .header { | ||||
| 		$height: 52px; | ||||
| 		$height-narrow: 42px; | ||||
| 		display: flex; | ||||
| 		flex-shrink: 0; | ||||
| 		box-shadow: 0px 1px var(--divider); | ||||
| 
 | ||||
| 		> button { | ||||
| 			height: $height; | ||||
| 			width: $height; | ||||
| 
 | ||||
| 			@media (max-width: 500px) { | ||||
| 				height: $height-narrow; | ||||
| 				width: $height-narrow; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .title { | ||||
| 			flex: 1; | ||||
| 			line-height: $height; | ||||
| 			padding-left: 32px; | ||||
| 			font-weight: bold; | ||||
| 			white-space: nowrap; | ||||
| 			overflow: hidden; | ||||
| 			text-overflow: ellipsis; | ||||
| 			pointer-events: none; | ||||
| 
 | ||||
| 			@media (max-width: 500px) { | ||||
| 				line-height: $height-narrow; | ||||
| 				padding-left: 16px; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> button + .title { | ||||
| 			padding-left: 0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .body { | ||||
| 		overflow: auto; | ||||
| 		background: var(--bg); | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div | ||||
| 	class="note _panel" | ||||
| 	class="note _block" | ||||
| 	v-if="!muted" | ||||
| 	v-show="!isDeleted" | ||||
| 	:tabindex="!isDeleted ? '-1' : null" | ||||
|  | @ -120,11 +120,11 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineAsyncComponent, defineComponent, markRaw, ref } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip, faShareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { parse } from '../../mfm/parse'; | ||||
| import { sum, unique } from '../../prelude/array'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| import XSub from './note.sub.vue'; | ||||
| import XNoteHeader from './note-header.vue'; | ||||
| import XNotePreview from './note-preview.vue'; | ||||
|  | @ -141,6 +141,7 @@ import { userPage } from '@client/filters/user'; | |||
| import * as os from '@client/os'; | ||||
| import { noteActions, noteViewInterruptors } from '@client/store'; | ||||
| import { reactionPicker } from '@client/scripts/reaction-picker'; | ||||
| import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; | ||||
| 
 | ||||
| function markRawAll(...xs) { | ||||
| 	for (const x of xs) { | ||||
|  | @ -252,21 +253,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 		urls(): string[] { | ||||
| 			if (this.appearNote.text) { | ||||
| 				const ast = parse(this.appearNote.text); | ||||
| 				// TODO: 再帰的にURL要素がないか調べる | ||||
| 				const urls = unique(ast | ||||
| 					.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent)) | ||||
| 					.map(t => t.node.props.url)); | ||||
| 
 | ||||
| 				// unique without hash | ||||
| 				// [ http://a/#1, http://a/#2, http://b/#3 ] => [ http://a/#1, http://b/#3 ] | ||||
| 				const removeHash = x => x.replace(/#[^#]*$/, ''); | ||||
| 
 | ||||
| 				return urls.reduce((array, url) => { | ||||
| 					const removed = removeHash(url); | ||||
| 					if (!array.map(x => removeHash(x)).includes(removed)) array.push(url); | ||||
| 					return array; | ||||
| 				}, []); | ||||
| 				return extractUrlFromMfm(mfm.parse(this.appearNote.text)); | ||||
| 			} else { | ||||
| 				return null; | ||||
| 			} | ||||
|  | @ -638,6 +625,11 @@ export default defineComponent({ | |||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
| 					} | ||||
| 				} : undefined, | ||||
| 				{ | ||||
| 					icon: faShareAlt, | ||||
| 					text: this.$ts.share, | ||||
| 					action: this.share | ||||
| 				}, | ||||
| 				null, | ||||
| 				statePromise.then(state => state.isFavorited ? { | ||||
| 					icon: faStar, | ||||
|  | @ -863,6 +855,14 @@ export default defineComponent({ | |||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		share() { | ||||
| 			navigator.share({ | ||||
| 				title: this.$t('noteOf', { user: this.appearNote.user.name }), | ||||
| 				text: this.appearNote.text, | ||||
| 				url: `${url}/notes/${this.appearNote.id}` | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		focus() { | ||||
| 			this.$el.focus(); | ||||
| 		}, | ||||
|  | @ -1020,7 +1020,7 @@ export default defineComponent({ | |||
| 						margin: 0 0.5em; | ||||
| 						padding: 4px 6px; | ||||
| 						font-size: 80%; | ||||
| 						border: solid 1px var(--divider); | ||||
| 						border: solid 0.5px var(--divider); | ||||
| 						border-radius: 4px; | ||||
| 					} | ||||
| 
 | ||||
|  | @ -1123,7 +1123,7 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> .reply { | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 	} | ||||
| 
 | ||||
| 	&.max-width_500px { | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ export default defineComponent({ | |||
| 		margin: 0 .5em 0 0; | ||||
| 		padding: 1px 6px; | ||||
| 		font-size: 80%; | ||||
| 		border: solid 1px var(--divider); | ||||
| 		border: solid 0.5px var(--divider); | ||||
| 		border-radius: 3px; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -139,7 +139,7 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> .reply { | ||||
| 		border-left: solid 1px var(--divider); | ||||
| 		border-left: solid 0.5px var(--divider); | ||||
| 		margin-top: 10px; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div | ||||
| 	class="tkcbzcuz _panel" | ||||
| 	class="tkcbzcuz" | ||||
| 	v-if="!muted" | ||||
| 	v-show="!isDeleted" | ||||
| 	:tabindex="!isDeleted ? '-1' : null" | ||||
|  | @ -90,7 +90,7 @@ | |||
| 		</div> | ||||
| 	</article> | ||||
| </div> | ||||
| <div v-else class="_panel muted" @click="muted = false"> | ||||
| <div v-else class="muted" @click="muted = false"> | ||||
| 	<I18n :src="$ts.userSaysSomething" tag="small"> | ||||
| 		<template #name> | ||||
| 			<MkA class="name" :to="userPage(appearNote.user)" v-user-preview="appearNote.userId"> | ||||
|  | @ -102,11 +102,11 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineAsyncComponent, defineComponent, markRaw, ref } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip, faShareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { parse } from '../../mfm/parse'; | ||||
| import { sum, unique } from '../../prelude/array'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| import XSub from './note.sub.vue'; | ||||
| import XNoteHeader from './note-header.vue'; | ||||
| import XNotePreview from './note-preview.vue'; | ||||
|  | @ -123,6 +123,7 @@ import { userPage } from '@client/filters/user'; | |||
| import * as os from '@client/os'; | ||||
| import { noteActions, noteViewInterruptors } from '@client/store'; | ||||
| import { reactionPicker } from '@client/scripts/reaction-picker'; | ||||
| import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; | ||||
| 
 | ||||
| function markRawAll(...xs) { | ||||
| 	for (const x of xs) { | ||||
|  | @ -238,21 +239,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 		urls(): string[] { | ||||
| 			if (this.appearNote.text) { | ||||
| 				const ast = parse(this.appearNote.text); | ||||
| 				// TODO: 再帰的にURL要素がないか調べる | ||||
| 				const urls = unique(ast | ||||
| 					.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent)) | ||||
| 					.map(t => t.node.props.url)); | ||||
| 
 | ||||
| 				// unique without hash | ||||
| 				// [ http://a/#1, http://a/#2, http://b/#3 ] => [ http://a/#1, http://b/#3 ] | ||||
| 				const removeHash = x => x.replace(/#[^#]*$/, ''); | ||||
| 
 | ||||
| 				return urls.reduce((array, url) => { | ||||
| 					const removed = removeHash(url); | ||||
| 					if (!array.map(x => removeHash(x)).includes(removed)) array.push(url); | ||||
| 					return array; | ||||
| 				}, []); | ||||
| 				return extractUrlFromMfm(mfm.parse(this.appearNote.text)); | ||||
| 			} else { | ||||
| 				return null; | ||||
| 			} | ||||
|  | @ -613,6 +600,11 @@ export default defineComponent({ | |||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
| 					} | ||||
| 				} : undefined, | ||||
| 				{ | ||||
| 					icon: faShareAlt, | ||||
| 					text: this.$ts.share, | ||||
| 					action: this.share | ||||
| 				}, | ||||
| 				null, | ||||
| 				statePromise.then(state => state.isFavorited ? { | ||||
| 					icon: faStar, | ||||
|  | @ -838,6 +830,14 @@ export default defineComponent({ | |||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		share() { | ||||
| 			navigator.share({ | ||||
| 				title: this.$t('noteOf', { user: this.appearNote.user.name }), | ||||
| 				text: this.appearNote.text, | ||||
| 				url: `${url}/notes/${this.appearNote.id}` | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		focus() { | ||||
| 			this.$el.focus(); | ||||
| 		}, | ||||
|  | @ -863,7 +863,7 @@ export default defineComponent({ | |||
| .tkcbzcuz { | ||||
| 	position: relative; | ||||
| 	transition: box-shadow 0.1s ease; | ||||
| 	overflow: hidden; | ||||
| 	overflow: clip; | ||||
| 	contain: content; | ||||
| 
 | ||||
| 	// これらの指定はパフォーマンス向上には有効だが、ノートの高さは一定でないため、 | ||||
|  | @ -994,11 +994,12 @@ export default defineComponent({ | |||
| 		> .avatar { | ||||
| 			flex-shrink: 0; | ||||
| 			display: block; | ||||
| 			//position: sticky; | ||||
| 			//top: 72px; | ||||
| 			margin: 0 14px 8px 0; | ||||
| 			width: 58px; | ||||
| 			height: 58px; | ||||
| 			position: sticky; | ||||
| 			top: calc(22px + var(--stickyTop, 0px)); | ||||
| 			left: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		> .main { | ||||
|  | @ -1119,7 +1120,7 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> .reply { | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 	} | ||||
| 
 | ||||
| 	&.max-width_500px { | ||||
|  | @ -1142,6 +1143,7 @@ export default defineComponent({ | |||
| 				margin: 0 10px 8px 0; | ||||
| 				width: 50px; | ||||
| 				height: 50px; | ||||
| 				top: calc(14px + var(--stickyTop, 0px)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class="_list_"> | ||||
| <div> | ||||
| 	<div class="_fullinfo" v-if="empty"> | ||||
| 		<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> | ||||
| 		<div>{{ $ts.noNotes }}</div> | ||||
|  | @ -15,7 +15,7 @@ | |||
| 	</div> | ||||
| 
 | ||||
| 	<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed"> | ||||
| 		<XNote :note="note" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/> | ||||
| 		<XNote :note="note" class="_block" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/> | ||||
| 	</XList> | ||||
| 
 | ||||
| 	<div v-show="more && !reversed" style="margin-top: var(--margin);"> | ||||
|  |  | |||
|  | @ -9,17 +9,19 @@ | |||
| 	@closed="$emit('closed')" | ||||
| > | ||||
| 	<template #header>{{ $ts.notificationSetting }}</template> | ||||
| 	<div v-if="showGlobalToggle" class="_section"> | ||||
| 		<MkSwitch v-model:value="useGlobalSetting"> | ||||
| 			{{ $ts.useGlobalSetting }} | ||||
| 			<template #desc>{{ $ts.useGlobalSettingDesc }}</template> | ||||
| 		</MkSwitch> | ||||
| 	</div> | ||||
| 	<div v-if="!useGlobalSetting" class="_section"> | ||||
| 		<MkInfo>{{ $ts.notificationSettingDesc }}</MkInfo> | ||||
| 		<MkButton inline @click="disableAll">{{ $ts.disableAll }}</MkButton> | ||||
| 		<MkButton inline @click="enableAll">{{ $ts.enableAll }}</MkButton> | ||||
| 		<MkSwitch v-for="type in notificationTypes" :key="type" v-model:value="typesMap[type]">{{ $t(`_notification._types.${type}`) }}</MkSwitch> | ||||
| 	<div class="_monolithic_"> | ||||
| 		<div v-if="showGlobalToggle" class="_section"> | ||||
| 			<MkSwitch v-model:value="useGlobalSetting"> | ||||
| 				{{ $ts.useGlobalSetting }} | ||||
| 				<template #desc>{{ $ts.useGlobalSettingDesc }}</template> | ||||
| 			</MkSwitch> | ||||
| 		</div> | ||||
| 		<div v-if="!useGlobalSetting" class="_section"> | ||||
| 			<MkInfo>{{ $ts.notificationSettingDesc }}</MkInfo> | ||||
| 			<MkButton inline @click="disableAll">{{ $ts.disableAll }}</MkButton> | ||||
| 			<MkButton inline @click="enableAll">{{ $ts.enableAll }}</MkButton> | ||||
| 			<MkSwitch v-for="type in notificationTypes" :key="type" v-model:value="typesMap[type]">{{ $t(`_notification._types.${type}`) }}</MkSwitch> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </XModalWindow> | ||||
| </template> | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| <template> | ||||
| <div class="mfcuwfyp _noGap_"> | ||||
| 	<div class="_magnet"></div> | ||||
| 	<XList class="notifications" :items="items" v-slot="{ item: notification }"> | ||||
| 		<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :note="notification.note" @update:note="noteUpdated(notification.note, $event)" :key="notification.id"/> | ||||
| 		<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj _panel" tabindex="-1"> | ||||
| <MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj _block _isolated" tabindex="-1"> | ||||
| 	<div class="thumbnail" v-if="page.eyeCatchingImage" :style="`background-image: url('${page.eyeCatchingImage.thumbnailUrl}')`"></div> | ||||
| 	<article> | ||||
| 		<header> | ||||
|  | @ -35,7 +35,6 @@ export default defineComponent({ | |||
| <style lang="scss" scoped> | ||||
| .vhpxefrj { | ||||
| 	display: block; | ||||
| 	width: 100%; | ||||
| 
 | ||||
| 	&:hover { | ||||
| 		text-decoration: none; | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| 		<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button> | ||||
| 		<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> | ||||
| 	</template> | ||||
| 	<div class="yrolvcoq" style="min-height: 100%; background: var(--bg);"> | ||||
| 	<div class="yrolvcoq _flat_"> | ||||
| 		<component :is="component" v-bind="props" :ref="changePage"/> | ||||
| 	</div> | ||||
| </XWindow> | ||||
|  | @ -29,6 +29,7 @@ import { popout } from '@client/scripts/popout'; | |||
| import copyToClipboard from '@client/scripts/copy-to-clipboard'; | ||||
| import { resolve } from '@client/router'; | ||||
| import { url } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -123,8 +124,8 @@ export default defineComponent({ | |||
| 	methods: { | ||||
| 		changePage(page) { | ||||
| 			if (page == null) return; | ||||
| 			if (page.INFO) { | ||||
| 				this.pageInfo = page.INFO; | ||||
| 			if (page[symbols.PAGE_INFO]) { | ||||
| 				this.pageInfo = page[symbols.PAGE_INFO]; | ||||
| 			} | ||||
| 		}, | ||||
| 
 | ||||
|  | @ -155,6 +156,7 @@ export default defineComponent({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .yrolvcoq { | ||||
| 	--section-padding: 16px; | ||||
| 	min-height: 100%; | ||||
| 	background: var(--bg); | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ | |||
| import { TextBlock } from '@client/scripts/hpml/block'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { defineAsyncComponent, defineComponent, PropType } from 'vue'; | ||||
| import { parse } from '../../../mfm/parse'; | ||||
| import { unique } from '../../../prelude/array'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -34,11 +34,7 @@ export default defineComponent({ | |||
| 	computed: { | ||||
| 		urls(): string[] { | ||||
| 			if (this.text) { | ||||
| 				const ast = parse(this.text); | ||||
| 				// TODO: 再帰的にURL要素がないか調べる | ||||
| 				return unique(ast | ||||
| 					.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent)) | ||||
| 					.map(t => t.node.props.url)); | ||||
| 				return extractUrlFromMfm(mfm.parse(this.text)); | ||||
| 			} else { | ||||
| 				return []; | ||||
| 			} | ||||
|  |  | |||
|  | @ -110,7 +110,7 @@ export default defineComponent({ | |||
| 			position: relative; | ||||
| 			margin: 4px 0; | ||||
| 			padding: 4px 8px; | ||||
| 			border: solid 1px var(--divider); | ||||
| 			border: solid 0.5px var(--divider); | ||||
| 			border-radius: 4px; | ||||
| 			overflow: hidden; | ||||
| 			cursor: pointer; | ||||
|  |  | |||
|  | @ -56,12 +56,12 @@ import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlob | |||
| import { faEyeSlash, faLaughSquint } from '@fortawesome/free-regular-svg-icons'; | ||||
| import insertTextAtCursor from 'insert-text-at-cursor'; | ||||
| import { length } from 'stringz'; | ||||
| import { toASCII } from 'punycode'; | ||||
| import { toASCII } from 'punycode/'; | ||||
| import XNotePreview from './note-preview.vue'; | ||||
| import { parse } from '../../mfm/parse'; | ||||
| 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 { extractMentions } from '@/misc/extract-mentions'; | ||||
| import getAcct from '@/misc/acct/render'; | ||||
| import { formatTimeString } from '@/misc/format-time-string'; | ||||
| import { Autocomplete } from '@client/scripts/autocomplete'; | ||||
|  | @ -229,7 +229,7 @@ export default defineComponent({ | |||
| 		} | ||||
| 
 | ||||
| 		if (this.reply && this.reply.text != null) { | ||||
| 			const ast = parse(this.reply.text); | ||||
| 			const ast = mfm.parse(this.reply.text); | ||||
| 
 | ||||
| 			for (const x of extractMentions(ast)) { | ||||
| 				const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`; | ||||
|  | @ -580,7 +580,7 @@ export default defineComponent({ | |||
| 					this.deleteDraft(); | ||||
| 					this.$emit('posted'); | ||||
| 					if (this.text && this.text != '') { | ||||
| 						const hashtags = parse(this.text).filter(x => x.node.type === 'hashtag').map(x => x.node.props.hashtag); | ||||
| 						const hashtags = mfm.parse(this.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag); | ||||
| 						const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; | ||||
| 						localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history)))); | ||||
| 					} | ||||
|  | @ -767,7 +767,7 @@ export default defineComponent({ | |||
| 		> .cw { | ||||
| 			z-index: 1; | ||||
| 			padding-bottom: 8px; | ||||
| 			border-bottom: solid 1px var(--divider); | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 		} | ||||
| 
 | ||||
| 		> .text { | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class="jmgmzlwq _panel"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/>{{ $ts.remoteUserCaution }}<a :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div> | ||||
| <div class="jmgmzlwq _block"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/>{{ $ts.remoteUserCaution }}<a :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <form class="eppvobhk" :class="{ signing, totpLogin }" @submit.prevent="onSubmit"> | ||||
| <form class="eppvobhk _monolithic_" :class="{ signing, totpLogin }" @submit.prevent="onSubmit"> | ||||
| 	<div class="auth _section"> | ||||
| 		<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div> | ||||
| 		<div class="normal-signin" v-if="!totpLogin"> | ||||
|  | @ -39,16 +39,16 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="social _section"> | ||||
| 		<a class="_borderButton _vMargin" v-if="meta && meta.enableTwitterIntegration" :href="`${apiUrl}/signin/twitter`"><Fa :icon="faTwitter" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Twitter' }) }}</a> | ||||
| 		<a class="_borderButton _vMargin" v-if="meta && meta.enableGithubIntegration" :href="`${apiUrl}/signin/github`"><Fa :icon="faGithub" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'GitHub' }) }}</a> | ||||
| 		<a class="_borderButton _vMargin" v-if="meta && meta.enableDiscordIntegration" :href="`${apiUrl}/signin/discord`"><Fa :icon="faDiscord" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Discord' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableTwitterIntegration" :href="`${apiUrl}/signin/twitter`"><Fa :icon="faTwitter" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Twitter' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableGithubIntegration" :href="`${apiUrl}/signin/github`"><Fa :icon="faGithub" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'GitHub' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableDiscordIntegration" :href="`${apiUrl}/signin/discord`"><Fa :icon="faDiscord" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Discord' }) }}</a> | ||||
| 	</div> | ||||
| </form> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { faLock, faGavel } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons'; | ||||
| import MkButton from './ui/button.vue'; | ||||
|  |  | |||
|  | @ -7,8 +7,10 @@ | |||
| > | ||||
| 	<template #header>{{ $ts.signup }}</template> | ||||
| 
 | ||||
| 	<div class="_section"> | ||||
| 		<XSignup :auto-set="autoSet" @signup="onSignup"/> | ||||
| 	<div class="_monolithic_"> | ||||
| 		<div class="_section"> | ||||
| 			<XSignup :auto-set="autoSet" @signup="onSignup"/> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </XModalWindow> | ||||
| </template> | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ | |||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { faLock, faExclamationTriangle, faSpinner, faCheck, faKey } from '@fortawesome/free-solid-svg-icons'; | ||||
| const getPasswordStrength = require('syuilo-password-strength'); | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { host, url } from '@client/config'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 	<template #header>Req Viewer</template> | ||||
| 
 | ||||
| 	<div class="rlkneywz"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 1px var(--divider);"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 			<option value="req">Request</option> | ||||
| 			<option value="res">Response</option> | ||||
| 		</MkTab> | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<Fa :icon="faTerminal" style="margin-right: 0.5em;"/>Task Manager | ||||
| 	</template> | ||||
| 	<div class="qljqmnzj _monospace"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 1px var(--divider);"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 			<option value="windows">Windows</option> | ||||
| 			<option value="stream">Stream</option> | ||||
| 			<option value="streamPool">Stream (Pool)</option> | ||||
|  | @ -215,7 +215,7 @@ export default defineComponent({ | |||
| 		width: 100%; | ||||
| 		padding: 8px 16px; | ||||
| 		box-sizing: border-box; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 		font-size: 0.9em; | ||||
| 
 | ||||
| 		> div { | ||||
|  |  | |||
|  | @ -56,6 +56,7 @@ export default defineComponent({ | |||
| 				includeLocalRenotes: this.$store.state.showLocalRenotes | ||||
| 			}, | ||||
| 			query: {}, | ||||
| 			date: null | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -157,7 +158,7 @@ export default defineComponent({ | |||
| 			endpoint: endpoint, | ||||
| 			limit: 10, | ||||
| 			params: init => ({ | ||||
| 				untilDate: init ? undefined : (this.date ? this.date.getTime() : undefined), | ||||
| 				untilDate: this.date?.getTime(), | ||||
| 				...this.baseQuery, ...this.query | ||||
| 			}) | ||||
| 		}; | ||||
|  | @ -171,6 +172,11 @@ export default defineComponent({ | |||
| 	methods: { | ||||
| 		focus() { | ||||
| 			this.$refs.tl.focus(); | ||||
| 		}, | ||||
| 
 | ||||
| 		timetravel(date?: Date) { | ||||
| 			this.date = date; | ||||
| 			this.$refs.tl.reload(); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class="ukygtjoj _panel" :class="{ naked, hideHeader: !showHeader, scrollable, closed: !showBody }" v-size="{ max: [380] }"> | ||||
| <div class="ukygtjoj _block" :class="{ naked, hideHeader: !showHeader, scrollable, closed: !showBody }" v-size="{ max: [380] }"> | ||||
| 	<header v-if="showHeader" ref="header"> | ||||
| 		<div class="title"><slot name="header"></slot></div> | ||||
| 		<div class="sub"> | ||||
|  | @ -116,7 +116,7 @@ export default defineComponent({ | |||
| 
 | ||||
| .ukygtjoj { | ||||
| 	position: relative; | ||||
| 	overflow: hidden; | ||||
| 	overflow: clip; | ||||
| 
 | ||||
| 	&.naked { | ||||
| 		background: transparent !important; | ||||
|  | @ -133,10 +133,12 @@ export default defineComponent({ | |||
| 	} | ||||
| 
 | ||||
| 	> header { | ||||
| 		position: relative; | ||||
| 		position: sticky; | ||||
| 		top: var(--stickyTop, 0px); | ||||
| 		left: 0; | ||||
| 		color: var(--panelHeaderFg); | ||||
| 		background: var(--panelHeaderBg); | ||||
| 		box-shadow: 0 1px 0 0 var(--panelHeaderDivider); | ||||
| 		border-bottom: solid 0.5px var(--panelHeaderDivider); | ||||
| 		z-index: 2; | ||||
| 		line-height: 1.4em; | ||||
| 
 | ||||
|  | @ -172,7 +174,7 @@ export default defineComponent({ | |||
| 			padding: 24px; | ||||
| 
 | ||||
| 			& + ._content { | ||||
| 				border-top: solid 1px var(--divider); | ||||
| 				border-top: solid 0.5px var(--divider); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -98,11 +98,12 @@ export default defineComponent({ | |||
| 	> header { | ||||
| 		display: flex; | ||||
| 		position: relative; | ||||
| 		z-index: 2; | ||||
| 		// TODO | ||||
| 		// position: sticky; | ||||
| 		// top: var(--stickyTopOffset); | ||||
| 		// backdrop-filter: blur(20px); | ||||
| 		z-index: 10; | ||||
| 		position: sticky; | ||||
| 		top: var(--stickyTop, 0px); | ||||
| 		background: var(--X17); | ||||
| 		-webkit-backdrop-filter: blur(8px); | ||||
| 		backdrop-filter: blur(20px); | ||||
| 
 | ||||
| 		> .title { | ||||
| 			margin: 0; | ||||
|  | @ -137,4 +138,10 @@ export default defineComponent({ | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._flat_ .ssazuxis { | ||||
| 	> header { | ||||
| 		padding: 0 16px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -53,4 +53,8 @@ export default defineComponent({ | |||
| 		margin-right: 4px; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._flat_ .fpezltsf { | ||||
| 	border-radius: 0; | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> | ||||
| 	<div class="ebkgoccj _popup _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: height ? `${height}px` : null }"> | ||||
| 	<div class="ebkgoccj _popup _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: scroll ? (height ? `${height}px` : null) :  (height ? `min(${height}px, 100%)` : '100%') }"> | ||||
| 		<div class="header"> | ||||
| 			<button class="_button" v-if="withOkButton" @click="$emit('close')"><Fa :icon="faTimes"/></button> | ||||
| 			<span class="title"> | ||||
|  | @ -61,6 +61,11 @@ export default defineComponent({ | |||
| 			required: false, | ||||
| 			default: true, | ||||
| 		}, | ||||
| 		scroll: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: true, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['click', 'close', 'closed', 'ok'], | ||||
|  | @ -94,10 +99,10 @@ export default defineComponent({ | |||
| 	flex-direction: column; | ||||
| 	contain: content; | ||||
| 
 | ||||
| 	--section-padding: 24px; | ||||
| 	--root-margin: 24px; | ||||
| 
 | ||||
| 	@media (max-width: 500px) { | ||||
| 		--section-padding: 16px; | ||||
| 		--root-margin: 16px; | ||||
| 	} | ||||
| 
 | ||||
| 	> .header { | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered"> | ||||
| <transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? popup ? 500 : 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered"> | ||||
| 	<div v-show="manualShowing != null ? manualShowing : showing" class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }"> | ||||
| 		<div class="bg _modalBg" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div> | ||||
| 		<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content"> | ||||
|  | @ -183,9 +183,6 @@ export default defineComponent({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .modal-enter-active, .modal-leave-active { | ||||
| 	// CSS的には無意味だけどこれが無いとVueが認識しない | ||||
| 	transition: opacity 0.3s, transform 0.3s !important; | ||||
| 
 | ||||
| 	> .bg { | ||||
| 		transition: opacity 0.3s !important; | ||||
| 	} | ||||
|  | @ -207,9 +204,6 @@ export default defineComponent({ | |||
| } | ||||
| 
 | ||||
| .modal-popup-enter-active, .modal-popup-leave-active { | ||||
| 	// CSS的には無意味だけどこれが無いとVueが認識しない | ||||
| 	transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), transform 0.5s cubic-bezier(0.16, 1, 0.3, 1) !important; | ||||
| 
 | ||||
| 	> .bg { | ||||
| 		transition: opacity 0.3s !important; | ||||
| 	} | ||||
|  |  | |||
|  | @ -395,7 +395,7 @@ export default defineComponent({ | |||
| 	position: fixed; | ||||
| 	top: 0; | ||||
| 	left: 0; | ||||
| 	z-index: 5000; | ||||
| 	z-index: 10000; // mk-modalのと同じでなければならない | ||||
| 
 | ||||
| 	&.front { | ||||
| 		z-index: 11000; // front指定の時は、mk-modalのよりも大きくなければならない | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ export default defineComponent({ | |||
| 	> .description { | ||||
| 		padding: 16px; | ||||
| 		font-size: 0.8em; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 		> .mfm { | ||||
| 			display: -webkit-box; | ||||
|  | @ -116,7 +116,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	> .status { | ||||
| 		padding: 10px 16px; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 		> div { | ||||
| 			display: inline-block; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <MkError v-if="error" @retry="init()"/> | ||||
| 
 | ||||
| <div v-else class="efvhhmdq"> | ||||
| <div v-else class="efvhhmdq _isolated"> | ||||
| 	<div class="no-users" v-if="empty"> | ||||
| 		<p>{{ $ts.noUsers }}</p> | ||||
| 	</div> | ||||
|  |  | |||
|  | @ -153,7 +153,7 @@ export default defineComponent({ | |||
| 		> .user { | ||||
| 			display: flex; | ||||
| 			align-items: center; | ||||
| 			padding: 8px var(--section-padding); | ||||
| 			padding: 8px var(--root-margin); | ||||
| 			font-size: 14px; | ||||
| 
 | ||||
| 			&:hover { | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	> .divider { | ||||
| 		margin: 8px 0; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 	} | ||||
| 
 | ||||
| 	> button { | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import tooltip from './tooltip'; | |||
| import hotkey from './hotkey'; | ||||
| import appear from './appear'; | ||||
| import anim from './anim'; | ||||
| import stickyContainer from './sticky-container'; | ||||
| 
 | ||||
| export default function(app: App) { | ||||
| 	app.directive('userPreview', userPreview); | ||||
|  | @ -17,4 +18,5 @@ export default function(app: App) { | |||
| 	app.directive('hotkey', hotkey); | ||||
| 	app.directive('appear', appear); | ||||
| 	app.directive('anim', anim); | ||||
| 	app.directive('sticky-container', stickyContainer); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/client/directives/sticky-container.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/client/directives/sticky-container.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| import { Directive } from 'vue'; | ||||
| 
 | ||||
| export default { | ||||
| 	mounted(src, binding, vn) { | ||||
| 		//const query = binding.value;
 | ||||
| 
 | ||||
| 		const header = src.children[0]; | ||||
| 		const currentStickyTop = getComputedStyle(src).getPropertyValue('--stickyTop') || '0px'; | ||||
| 		src.style.setProperty('--stickyTop', `${parseInt(currentStickyTop) + header.offsetHeight}px`); | ||||
| 		header.style.setProperty('--stickyTop', currentStickyTop); | ||||
| 		header.style.position = 'sticky'; | ||||
| 		header.style.top = 'var(--stickyTop)'; | ||||
| 		header.style.zIndex = '1'; | ||||
| 	}, | ||||
| } as Directive; | ||||
|  | @ -6,7 +6,7 @@ import '@client/style.scss'; | |||
| 
 | ||||
| import * as Sentry from '@sentry/browser'; | ||||
| import { Integrations } from '@sentry/tracing'; | ||||
| import { createApp, watch } from 'vue'; | ||||
| import { computed, createApp, watch } from 'vue'; | ||||
| import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; | ||||
| 
 | ||||
| import widgets from '@client/widgets'; | ||||
|  | @ -25,7 +25,6 @@ import { fetchInstance, instance } from '@client/instance'; | |||
| import { makeHotkey } from '@client/scripts/hotkey'; | ||||
| import { search } from '@client/scripts/search'; | ||||
| import { isMobile } from '@client/scripts/is-mobile'; | ||||
| import { getThemes } from '@client/theme-store'; | ||||
| import { initializeSw } from '@client/scripts/initialize-sw'; | ||||
| import { reloadChannel } from '@client/scripts/unison-reload'; | ||||
| import { reactionPicker } from '@client/scripts/reaction-picker'; | ||||
|  | @ -36,6 +35,13 @@ 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')); | ||||
| } | ||||
| 
 | ||||
| if (_DEV_) { | ||||
| 	console.warn('Development mode!!!'); | ||||
| 
 | ||||
|  | @ -161,6 +167,7 @@ const app = createApp(await ( | |||
| 	ui === 'deck'                     ? import('@client/ui/deck.vue') : | ||||
| 	ui === 'desktop'                  ? import('@client/ui/desktop.vue') : | ||||
| 	ui === 'chat'                     ? import('@client/ui/chat/index.vue') : | ||||
| 	ui === 'pope'                     ? import('@client/ui/universal.vue') : | ||||
| 	import('@client/ui/default.vue') | ||||
| ).then(x => x.default)); | ||||
| 
 | ||||
|  | @ -204,12 +211,24 @@ if (splash) { | |||
| } | ||||
| 
 | ||||
| watch(defaultStore.reactiveState.darkMode, (darkMode) => { | ||||
| 	import('@client/scripts/theme').then(({ builtinThemes }) => { | ||||
| 		const themes = builtinThemes.concat(getThemes()); | ||||
| 		applyTheme(themes.find(x => x.id === (darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')))); | ||||
| 	}); | ||||
| 	applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')); | ||||
| }, { immediate: localStorage.theme == null }); | ||||
| 
 | ||||
| const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); | ||||
| const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); | ||||
| 
 | ||||
| watch(darkTheme, (theme) => { | ||||
| 	if (defaultStore.state.darkMode) { | ||||
| 		applyTheme(theme); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| watch(lightTheme, (theme) => { | ||||
| 	if (!defaultStore.state.darkMode) { | ||||
| 		applyTheme(theme); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| //#region Sync dark mode
 | ||||
| if (ColdDeviceStorage.get('syncDeviceDarkMode')) { | ||||
| 	defaultStore.set('darkMode', isDeviceDarkmode()); | ||||
|  |  | |||
|  | @ -203,6 +203,15 @@ export function pageWindow(path: string) { | |||
| 	}, {}, 'closed'); | ||||
| } | ||||
| 
 | ||||
| export function modalPageWindow(path: string) { | ||||
| 	const { component, props } = resolve(path); | ||||
| 	popup(import('@client/components/modal-page-window.vue'), { | ||||
| 		initialPath: path, | ||||
| 		initialComponent: markRaw(component), | ||||
| 		initialProps: props, | ||||
| 	}, {}, 'closed'); | ||||
| } | ||||
| 
 | ||||
| export function dialog(props: Record<string, any>) { | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		popup(import('@client/components/dialog.vue'), props, { | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -21,7 +22,7 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.error, | ||||
| 				icon: faExclamationTriangle | ||||
| 			}, | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div style="overflow: hidden;"> | ||||
| <div style="overflow: clip;"> | ||||
| 	<FormBase class="znqjceqz"> | ||||
| 		<div id="debug"></div> | ||||
| 		<section class="_formItem about"> | ||||
|  | @ -14,7 +14,7 @@ | |||
| 			{{ $ts._aboutMisskey.about }} | ||||
| 		</section> | ||||
| 		<FormGroup> | ||||
| 			<FormLink to="https://github.com/syuilo/misskey" external> | ||||
| 			<FormLink to="https://github.com/misskey-dev/misskey" external> | ||||
| 				<template #icon><Fa :icon="faCode"/></template> | ||||
| 				{{ $ts._aboutMisskey.source }} | ||||
| 				<template #suffix>GitHub</template> | ||||
|  | @ -40,7 +40,8 @@ | |||
| 			<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink> | ||||
| 			<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink> | ||||
| 			<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink> | ||||
| 			<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $ts._aboutMisskey.allContributors }}</MkLink></template> | ||||
| 			<FormLink to="https://github.com/marihachi" external>@marihachi</FormLink> | ||||
| 			<template #caption><MkLink url="https://github.com/misskey-dev/misskey/graphs/contributors">{{ $ts._aboutMisskey.allContributors }}</MkLink></template> | ||||
| 		</FormGroup> | ||||
| 		<FormGroup> | ||||
| 			<template #label><Mfm text="[jelly ❤]"/> {{ $ts._aboutMisskey.patrons }}</template> | ||||
|  | @ -63,6 +64,7 @@ import FormKeyValueView from '@client/components/form/key-value-view.vue'; | |||
| import MkLink from '@client/components/link.vue'; | ||||
| import { physics } from '@client/scripts/physics.ts'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| const patrons = [ | ||||
| 	'Satsuki Yanagi', | ||||
|  | @ -114,7 +116,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.aboutMisskey, | ||||
| 				icon: null | ||||
| 			}, | ||||
|  |  | |||
|  | @ -48,6 +48,7 @@ import FormGroup from '@client/components/form/group.vue'; | |||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import number from '@client/filters/number'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -59,7 +60,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.instanceInfo, | ||||
| 				icon: faInfoCircle | ||||
| 			}, | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| 		</div> | ||||
| 	</section> | ||||
| 	<section class="_section"> | ||||
| 		<div class="_content _card _vMargin"> | ||||
| 		<div class="_content _card _gap"> | ||||
| 			<div class="_content"> | ||||
| 				<MkInput v-model:value="name" required><span>{{ $ts.name }}</span></MkInput> | ||||
| 				<MkInput v-model:value="author" required><span>{{ $ts.author }}</span></MkInput> | ||||
|  | @ -24,7 +24,7 @@ | |||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="_content _card _vMargin"> | ||||
| 		<div class="_content _card _gap"> | ||||
| 			<div class="list-view _content"> | ||||
| 				<div class="item" v-for="([ k, v ], i) in theme" :key="k"> | ||||
| 					<div class="_inputs"> | ||||
|  | @ -94,7 +94,7 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { faPalette, faChevronDown, faKeyboard } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as JSON5 from 'json5'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| 
 | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
|  | @ -109,6 +109,7 @@ import { host } from '@client/config'; | |||
| import * as os from '@client/os'; | ||||
| import { ColdDeviceStorage } from '@client/store'; | ||||
| import { addTheme } from '@client/theme-store'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -122,7 +123,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.themeEditor, | ||||
| 				icon: faPalette, | ||||
| 			}, | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="_section"> | ||||
| 	<MkPagination :pagination="pagination" #default="{items}" class="ruryvtyk _content"> | ||||
| 		<section class="_card announcement _vMargin" v-for="(announcement, i) in items" :key="announcement.id"> | ||||
| 		<section class="_card announcement _gap" v-for="(announcement, i) in items" :key="announcement.id"> | ||||
| 			<div class="_title"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div> | ||||
| 			<div class="_content"> | ||||
| 				<Mfm :text="announcement.text"/> | ||||
|  | @ -21,6 +21,7 @@ import { faCheck, faBroadcastTower } from '@fortawesome/free-solid-svg-icons'; | |||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -30,7 +31,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.announcements, | ||||
| 				icon: faBroadcastTower | ||||
| 			}, | ||||
|  |  | |||
|  | @ -1,25 +1,25 @@ | |||
| <template> | ||||
| <div> | ||||
| <section class="_section"> | ||||
| 	<MkInput v-model:value="endpoint" :datalist="endpoints" @update:value="onEndpointChange()"> | ||||
| 		<span>Endpoint</span> | ||||
| 	</MkInput> | ||||
| 	<MkTextarea v-model:value="body" code> | ||||
| 		<span>Params (JSON or JSON5)</span> | ||||
| 	</MkTextarea> | ||||
| 	<MkSwitch v-model:value="withCredential"> | ||||
| 		With credential | ||||
| 	</MkSwitch> | ||||
| 	<MkButton primary full @click="send" :disabled="sending"> | ||||
| 		<template v-if="sending"><MkEllipsis/></template> | ||||
| 		<template v-else><Fa :icon="faPaperPlane"/> Send</template> | ||||
| 	</MkButton> | ||||
| </section> | ||||
| <section class="_section" v-if="res"> | ||||
| 	<MkTextarea v-model:value="res" code readonly tall> | ||||
| 		<span>Response</span> | ||||
| 	</MkTextarea> | ||||
| </section> | ||||
| <div class="_root"> | ||||
| 	<div class="_block" style="padding: 24px;"> | ||||
| 		<MkInput v-model:value="endpoint" :datalist="endpoints" @update:value="onEndpointChange()"> | ||||
| 			<span>Endpoint</span> | ||||
| 		</MkInput> | ||||
| 		<MkTextarea v-model:value="body" code> | ||||
| 			<span>Params (JSON or JSON5)</span> | ||||
| 		</MkTextarea> | ||||
| 		<MkSwitch v-model:value="withCredential"> | ||||
| 			With credential | ||||
| 		</MkSwitch> | ||||
| 		<MkButton primary full @click="send" :disabled="sending"> | ||||
| 			<template v-if="sending"><MkEllipsis/></template> | ||||
| 			<template v-else><Fa :icon="faPaperPlane"/> Send</template> | ||||
| 		</MkButton> | ||||
| 	</div> | ||||
| 	<div v-if="res" class="_block" style="padding: 24px;"> | ||||
| 		<MkTextarea v-model:value="res" code readonly tall> | ||||
| 			<span>Response</span> | ||||
| 		</MkTextarea> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -32,6 +32,7 @@ import MkInput from '@client/components/ui/input.vue'; | |||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkSwitch from '@client/components/ui/switch.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -40,7 +41,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: 'API console', | ||||
| 				icon: faTerminal | ||||
| 			}, | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ import MkButton from '@client/components/ui/button.vue'; | |||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import { selectFile } from '@client/scripts/select-file'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -45,7 +46,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: computed(() => this.channelId ? { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.channelId ? { | ||||
| 				title: this.$ts._channel.edit, | ||||
| 				icon: faSatelliteDish, | ||||
| 			} : { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div v-if="channel" class="_section"> | ||||
| 	<div class="wpgynlbz _content _panel _vMargin" :class="{ hide: !showBanner }"> | ||||
| 	<div class="wpgynlbz _content _panel _gap" :class="{ hide: !showBanner }"> | ||||
| 		<XChannelFollowButton :channel="channel" :full="true" class="subscribe"/> | ||||
| 		<button class="_button toggle" @click="() => showBanner = !showBanner"> | ||||
| 			<template v-if="showBanner"><Fa :icon="faAngleUp"/></template> | ||||
|  | @ -20,9 +20,9 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<XPostForm :channel="channel" class="post-form _content _panel _vMargin" fixed v-if="$i"/> | ||||
| 	<XPostForm :channel="channel" class="post-form _content _panel _gap" fixed v-if="$i"/> | ||||
| 
 | ||||
| 	<XTimeline class="_content _vMargin _noGap_" src="channel" :key="channelId" :channel="channelId" @before="before" @after="after"/> | ||||
| 	<XTimeline class="_content _gap _noGap_" src="channel" :key="channelId" :channel="channelId" @before="before" @after="after"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -35,6 +35,7 @@ import XPostForm from '@client/components/post-form.vue'; | |||
| import XTimeline from '@client/components/timeline.vue'; | ||||
| import XChannelFollowButton from '@client/components/channel-follow-button.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -53,7 +54,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: computed(() => this.channel ? { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.channel ? { | ||||
| 				title: this.channel.name, | ||||
| 				icon: faSatelliteDish, | ||||
| 			} : null), | ||||
|  |  | |||
|  | @ -11,20 +11,20 @@ | |||
| 	<div class="_section"> | ||||
| 		<div class="_content grwlizim featured" v-if="tab === 'featured'"> | ||||
| 			<MkPagination :pagination="featuredPagination" #default="{items}"> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_vMargin" :channel="channel" :key="channel.id"/> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/> | ||||
| 			</MkPagination> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div class="_content grwlizim following" v-if="tab === 'following'"> | ||||
| 			<MkPagination :pagination="followingPagination" #default="{items}"> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_vMargin" :channel="channel" :key="channel.id"/> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/> | ||||
| 			</MkPagination> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div class="_content grwlizim owned" v-if="tab === 'owned'"> | ||||
| 			<MkButton class="new" @click="create()"><Fa :icon="faPlus"/></MkButton> | ||||
| 			<MkPagination :pagination="ownedPagination" #default="{items}"> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_vMargin" :channel="channel" :key="channel.id"/> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/> | ||||
| 			</MkPagination> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | @ -39,6 +39,7 @@ import MkChannelPreview from '@client/components/channel-preview.vue'; | |||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkTab from '@client/components/tab.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -46,7 +47,7 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.channel, | ||||
| 				icon: faSatelliteDish, | ||||
| 				action: { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div v-if="clip" class="_section"> | ||||
| 	<div class="okzinsic _content _panel _vMargin"> | ||||
| 	<div class="okzinsic _content _panel _gap"> | ||||
| 		<div class="description" v-if="clip.description"> | ||||
| 			<Mfm :text="clip.description" :is-note="false" :i="$i"/> | ||||
| 		</div> | ||||
|  | @ -9,7 +9,7 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<XNotes class="_content _vMargin" :pagination="pagination" :detail="true"/> | ||||
| 	<XNotes class="_content _gap" :pagination="pagination" :detail="true"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -20,6 +20,7 @@ import MkContainer from '@client/components/ui/container.vue'; | |||
| import XPostForm from '@client/components/post-form.vue'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -37,7 +38,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: computed(() => this.clip ? { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.clip ? { | ||||
| 				title: this.clip.name, | ||||
| 				icon: faPaperclip, | ||||
| 				action: { | ||||
|  | @ -142,7 +143,7 @@ export default defineComponent({ | |||
| 	> .user { | ||||
| 		$height: 32px; | ||||
| 		padding: 16px; | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 		line-height: $height; | ||||
| 
 | ||||
| 		> .avatar { | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<div class="title">{{ title }}</div> | ||||
| 	<div class="body" v-html="body"></div> | ||||
| 	<div class="footer"> | ||||
| 		<MkLink :url="`https://github.com/syuilo/misskey/blob/master/src/docs/${lang}/${doc}.md`" class="at">{{ $ts.docSource }}</MkLink> | ||||
| 		<MkLink :url="`https://github.com/misskey-dev/misskey/blob/master/src/docs/${lang}/${doc}.md`" class="at">{{ $ts.docSource }}</MkLink> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -15,6 +15,7 @@ import MarkdownIt from 'markdown-it'; | |||
| import MarkdownItAnchor from 'markdown-it-anchor'; | ||||
| import { url, lang } from '@client/config'; | ||||
| import MkLink from '@client/components/link.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| const markdown = MarkdownIt({ | ||||
| 	html: true | ||||
|  | @ -38,7 +39,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: computed(() => this.title ? { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.title ? { | ||||
| 				title: this.title, | ||||
| 				icon: faQuestionCircle, | ||||
| 			} : null), | ||||
|  | @ -150,7 +151,7 @@ export default defineComponent({ | |||
| 			font-size: 1.25em; | ||||
| 			padding: 0 0 0.5em 0; | ||||
| 			margin: 1.5em 0 1em 0; | ||||
| 			border-bottom: solid 1px var(--divider); | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 		} | ||||
| 
 | ||||
| 		::v-deep(table) { | ||||
|  | @ -170,7 +171,7 @@ export default defineComponent({ | |||
| 		::v-deep(kbd.key) { | ||||
| 			display: inline-block; | ||||
| 			padding: 6px 8px; | ||||
| 			border: solid 1px var(--divider); | ||||
| 			border: solid 0.5px var(--divider); | ||||
| 			border-radius: 4px; | ||||
| 			box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); | ||||
| 		} | ||||
|  |  | |||
|  | @ -16,11 +16,12 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons' | ||||
| import { url, lang } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.help, | ||||
| 				icon: faQuestionCircle | ||||
| 			}, | ||||
|  |  | |||
|  | @ -6,9 +6,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faCloud, faEllipsisH } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCloud } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XDrive from '@client/components/drive.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -17,22 +18,13 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: computed(() => this.folder ? this.folder.name : this.$ts.drive), | ||||
| 				icon: faCloud, | ||||
| 				action: { | ||||
| 					icon: faEllipsisH, | ||||
| 					handler: this.menu | ||||
| 				} | ||||
| 				menu: () => this.$refs.drive.getMenu() | ||||
| 			}, | ||||
| 			folder: null, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		menu(ev) { | ||||
| 			os.modalMenu(this.$refs.drive.getMenu(), ev.currentTarget || ev.target); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -1,40 +1,42 @@ | |||
| <template> | ||||
| <div class="lznhrdub"> | ||||
| 	<div class="_section"> | ||||
| 		<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.searchUser }}</span></MkInput> | ||||
| <div class="lznhrdub _root"> | ||||
| 	<div> | ||||
| 		<div class="_isolated"> | ||||
| 			<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.searchUser }}</span></MkInput> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<XUserList v-if="query" class="_vMargin" :pagination="searchPagination" ref="search"/> | ||||
| 		<XUserList v-if="query" class="_gap" :pagination="searchPagination" ref="search"/> | ||||
| 
 | ||||
| 		<div class="localfedi7 _panel _vMargin" v-if="meta && stats && tag == null" :style="{ backgroundImage: meta.bannerUrl ? `url(${meta.bannerUrl})` : null }"> | ||||
| 		<div class="localfedi7 _block _isolated" v-if="meta && stats && tag == null" :style="{ backgroundImage: meta.bannerUrl ? `url(${meta.bannerUrl})` : null }"> | ||||
| 			<header><span>{{ $t('explore', { host: meta.name || 'Misskey' }) }}</span></header> | ||||
| 			<div><span>{{ $t('exploreUsersCount', { count: num(stats.originalUsersCount) }) }}</span></div> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<template v-if="tag == null"> | ||||
| 			<MkFolder class="_vMargin" persist-key="explore-pinned-users"> | ||||
| 			<MkFolder class="_gap" persist-key="explore-pinned-users"> | ||||
| 				<template #header><Fa :icon="faBookmark" fixed-width style="margin-right: 0.5em;"/>{{ $ts.pinnedUsers }}</template> | ||||
| 				<XUserList :pagination="pinnedUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_vMargin" persist-key="explore-popular-users"> | ||||
| 			<MkFolder class="_gap" persist-key="explore-popular-users"> | ||||
| 				<template #header><Fa :icon="faChartLine" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularUsers }}</template> | ||||
| 				<XUserList :pagination="popularUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_vMargin" persist-key="explore-recently-updated-users"> | ||||
| 			<MkFolder class="_gap" persist-key="explore-recently-updated-users"> | ||||
| 				<template #header><Fa :icon="faCommentAlt" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyUpdatedUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_vMargin" persist-key="explore-recently-registered-users"> | ||||
| 			<MkFolder class="_gap" persist-key="explore-recently-registered-users"> | ||||
| 				<template #header><Fa :icon="faPlus" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyRegisteredUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyRegisteredUsers"/> | ||||
| 			</MkFolder> | ||||
| 		</template> | ||||
| 	</div> | ||||
| 	<div class="_section"> | ||||
| 		<div class="localfedi7 _panel _vMargin" v-if="tag == null" :style="{ backgroundImage: `url(/static-assets/client/fedi.jpg)` }"> | ||||
| 	<div> | ||||
| 		<div class="localfedi7 _block _isolated" v-if="tag == null" :style="{ backgroundImage: `url(/static-assets/client/fedi.jpg)` }"> | ||||
| 			<header><span>{{ $ts.exploreFediverse }}</span></header> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<MkFolder :body-togglable="true" :expanded="false" ref="tags" class="_vMargin"> | ||||
| 		<MkFolder :body-togglable="true" :expanded="false" ref="tags" class="_gap"> | ||||
| 			<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularTags }}</template> | ||||
| 
 | ||||
| 			<div class="vxjfqztj"> | ||||
|  | @ -43,21 +45,21 @@ | |||
| 			</div> | ||||
| 		</MkFolder> | ||||
| 
 | ||||
| 		<MkFolder v-if="tag != null" :key="`${tag}`" class="_vMargin"> | ||||
| 		<MkFolder v-if="tag != null" :key="`${tag}`" class="_gap"> | ||||
| 			<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ tag }}</template> | ||||
| 			<XUserList :pagination="tagUsers"/> | ||||
| 		</MkFolder> | ||||
| 
 | ||||
| 		<template v-if="tag == null"> | ||||
| 			<MkFolder class="_vMargin"> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faChartLine" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularUsers }}</template> | ||||
| 				<XUserList :pagination="popularUsersF"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_vMargin"> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faCommentAlt" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyUpdatedUsersF"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_vMargin"> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faRocket" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyDiscoveredUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyRegisteredUsersF"/> | ||||
| 			</MkFolder> | ||||
|  | @ -75,6 +77,7 @@ import MkFolder from '@client/components/ui/folder.vue'; | |||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import number from '@client/filters/number'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -92,7 +95,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.explore, | ||||
| 				icon: faHashtag | ||||
| 			}, | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import { faStar } from '@fortawesome/free-solid-svg-icons'; | |||
| import Progress from '@client/scripts/loading'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -18,7 +19,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.favorites, | ||||
| 				icon: faStar | ||||
| 			}, | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import { defineComponent } from 'vue'; | |||
| import { faFireAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Progress from '@client/scripts/loading'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -17,7 +18,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.featured, | ||||
| 				icon: faFireAlt | ||||
| 			}, | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ import { faUserClock, faCheck, faTimes } from '@fortawesome/free-solid-svg-icons | |||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import { userPage, acct } from '../filters/user'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -43,7 +44,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.followRequests, | ||||
| 				icon: faUserClock, | ||||
| 			}, | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ | |||
| 			--> | ||||
| 
 | ||||
| 			<MkPagination :pagination="pagination" #default="{items}" ref="reports" style="margin-top: var(--margin);"> | ||||
| 				<div class="bcekxzvu _card _vMargin" v-for="report in items" :key="report.id"> | ||||
| 				<div class="bcekxzvu _card _gap" v-for="report in items" :key="report.id"> | ||||
| 					<div class="_content target"> | ||||
| 						<MkAvatar class="avatar" :user="report.targetUser"/> | ||||
| 						<div class="info"> | ||||
|  | @ -72,6 +72,7 @@ import MkSelect from '@client/components/ui/select.vue'; | |||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import { acct } from '../../filters/user'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -83,7 +84,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.abuseReports, | ||||
| 				icon: faExclamationCircle | ||||
| 			}, | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<div class="_section"> | ||||
| 		<div class="_content"> | ||||
| 			<MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> | ||||
| 			<section class="_card _vMargin announcements" v-for="announcement in announcements"> | ||||
| 			<section class="_card _gap announcements" v-for="announcement in announcements"> | ||||
| 				<div class="_content announcement"> | ||||
| 					<MkInput v-model:value="announcement.title"> | ||||
| 						<span>{{ $ts.title }}</span> | ||||
|  | @ -34,6 +34,7 @@ import MkButton from '@client/components/ui/button.vue'; | |||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -44,7 +45,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.announcements, | ||||
| 				icon: faBroadcastTower | ||||
| 			}, | ||||
|  |  | |||
|  | @ -59,6 +59,7 @@ import MkPagination from '@client/components/ui/pagination.vue'; | |||
| import MkTab from '@client/components/tab.vue'; | ||||
| import { selectFile } from '@client/scripts/select-file'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -70,7 +71,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.customEmojis, | ||||
| 				icon: faLaugh, | ||||
| 				action: { | ||||
|  |  | |||
|  | @ -67,6 +67,7 @@ import MkSelect from '@client/components/ui/select.vue'; | |||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkInstanceInfo from './instance.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -78,7 +79,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.federation, | ||||
| 				icon: faGlobe | ||||
| 			}, | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
| 				</MkInput> | ||||
| 			</div> | ||||
| 			<MkPagination :pagination="pagination" #default="{items}" class="urempief" ref="files"> | ||||
| 				<button class="file _panel _button _vMargin" v-for="file in items" :key="file.id" @click="show(file, $event)"> | ||||
| 				<button class="file _panel _button _gap" v-for="file in items" :key="file.id" @click="show(file, $event)"> | ||||
| 					<MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/> | ||||
| 					<div class="body"> | ||||
| 						<div> | ||||
|  | @ -71,6 +71,7 @@ import MkPagination from '@client/components/ui/pagination.vue'; | |||
| import MkDriveFileThumbnail from '@client/components/drive-file-thumbnail.vue'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -83,7 +84,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.files, | ||||
| 				icon: faCloud | ||||
| 			}, | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<template #header><Fa :icon="faHeartbeat"/> {{ $ts.metrics }}</template> | ||||
| 		<div class="_section" style="padding: 0 var(--margin);"> | ||||
| 			<div class="_content"> | ||||
| 				<MkContainer :body-togglable="false" class="_vMargin"> | ||||
| 				<MkContainer :body-togglable="false" class="_gap"> | ||||
| 					<template #header><Fa :icon="faMicrochip"/>{{ $ts.cpuAndMemory }}</template> | ||||
| 					<!-- | ||||
| 					<template #func> | ||||
|  | @ -27,7 +27,7 @@ | |||
| 					</div> | ||||
| 				</MkContainer> | ||||
| 
 | ||||
| 				<MkContainer :body-togglable="false" class="_vMargin"> | ||||
| 				<MkContainer :body-togglable="false" class="_gap"> | ||||
| 					<template #header><Fa :icon="faHdd"/> {{ $ts.disk }}</template> | ||||
| 					<!-- | ||||
| 					<template #func> | ||||
|  | @ -50,7 +50,7 @@ | |||
| 					</div> | ||||
| 				</MkContainer> | ||||
| 
 | ||||
| 				<MkContainer :body-togglable="false" class="_vMargin"> | ||||
| 				<MkContainer :body-togglable="false" class="_gap"> | ||||
| 					<template #header><Fa :icon="faExchangeAlt"/> {{ $ts.network }}</template> | ||||
| 					<!-- | ||||
| 					<template #func> | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ | |||
| 		<template #header><Fa :icon="faTachometerAlt"/> {{ $ts.overview }}</template> | ||||
| 
 | ||||
| 		<div class="sboqnrfi" :style="{ gridTemplateRows: overviewHeight }"> | ||||
| 			<MkInstanceStats :chart-limit="300" :detailed="true" class="_vMargin" ref="stats"/> | ||||
| 			<MkInstanceStats :chart-limit="300" :detailed="true" class="_gap" ref="stats"/> | ||||
| 
 | ||||
| 			<MkContainer :body-togglable="true" class="_vMargin"> | ||||
| 			<MkContainer :body-togglable="true" class="_gap"> | ||||
| 				<template #header><Fa :icon="faInfoCircle"/>{{ $ts.instanceInfo }}</template> | ||||
| 
 | ||||
| 				<div class="_content"> | ||||
|  | @ -19,7 +19,7 @@ | |||
| 				</div> | ||||
| 			</MkContainer> | ||||
| 			 | ||||
| 			<MkContainer :body-togglable="true" :scrollable="true" class="_vMargin" style="height: 300px;"> | ||||
| 			<MkContainer :body-togglable="true" :scrollable="true" class="_gap" style="height: 300px;"> | ||||
| 				<template #header><Fa :icon="faDatabase"/>{{ $ts.database }}</template> | ||||
| 
 | ||||
| 				<div class="_content" v-if="dbInfo"> | ||||
|  | @ -70,6 +70,7 @@ import number from '../../filters/number'; | |||
| import MkInstanceInfo from './instance.vue'; | ||||
| import XMetrics from './index.metrics.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -85,7 +86,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				tabs: [{ | ||||
| 					id: 'index', | ||||
| 					title: null, | ||||
|  |  | |||
|  | @ -500,12 +500,12 @@ export default defineComponent({ | |||
| 		} | ||||
| 
 | ||||
| 		&:not(:first-child) { | ||||
| 			border-top: solid 1px var(--divider); | ||||
| 			border-top: solid 0.5px var(--divider); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .chart { | ||||
| 		border-top: solid 1px var(--divider); | ||||
| 		border-top: solid 0.5px var(--divider); | ||||
| 		padding: 16px 0 12px 0; | ||||
| 
 | ||||
| 		> .header { | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ import MkInput from '@client/components/ui/input.vue'; | |||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -48,7 +49,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			INFO: { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.serverLogs, | ||||
| 				icon: faStream | ||||
| 			}, | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue