feat(client): 翻訳をIndexedDBに保存・プッシュ通知を翻訳 (#6396)
* wip * tabun ok * better msg * oops * fix lint * Update gulpfile.ts Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com> * Update src/client/scripts/set-i18n-contexts.ts Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com> * refactor Co-authored-by: acid-chicken <root@acid-chicken.com> * ✨ * wip * fix lint * たぶんおk * fix flush * Translate Notification * remove console.log * fix * add notifications * remove san * wip * ok * ✌️ * Update src/prelude/array.ts Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com> * wip * i18n refactor * Update init.ts * ✌️ Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com> Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
This commit is contained in:
		
							parent
							
								
									11141c878c
								
							
						
					
					
						commit
						3963ed8ff7
					
				
					 143 changed files with 290 additions and 433 deletions
				
			
		|  | @ -11,7 +11,7 @@ const cleanCSS = require('gulp-clean-css'); | |||
| const sass = require('gulp-dart-sass'); | ||||
| const fiber = require('fibers'); | ||||
| 
 | ||||
| const locales = require('./locales'); | ||||
| const locales: { [x: string]: any } = require('./locales'); | ||||
| const meta = require('./package.json'); | ||||
| 
 | ||||
| gulp.task('build:ts', () => { | ||||
|  | @ -31,8 +31,10 @@ gulp.task('build:copy:views', () => | |||
| gulp.task('build:copy:locales', cb => { | ||||
| 	fs.mkdirSync('./built/client/assets/locales', { recursive: true }); | ||||
| 
 | ||||
| 	const v = { '_version_': meta.version }; | ||||
| 
 | ||||
| 	for (const [lang, locale] of Object.entries(locales)) { | ||||
| 		fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify(locale), 'utf-8'); | ||||
| 		fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8'); | ||||
| 	} | ||||
| 
 | ||||
| 	cb(); | ||||
|  |  | |||
|  | @ -507,6 +507,8 @@ addRelay: "リレーの追加" | |||
| inboxUrl: "inboxのURL" | ||||
| addedRelays: "追加済みのリレー" | ||||
| serviceworkerInfo: "プッシュ通知を行うには有効する必要があります。" | ||||
| deletedNote: "削除された投稿" | ||||
| invisibleNote: "非公開の投稿" | ||||
| 
 | ||||
| _theme: | ||||
|   explore: "テーマを探す" | ||||
|  | @ -1102,3 +1104,17 @@ _relayStatus: | |||
|   requesting: "承認待ち" | ||||
|   accepted: "承認済み" | ||||
|   rejected: "拒否済み" | ||||
| 
 | ||||
| _notification: | ||||
|   fileUploaded: "ファイルがアップロードされました" | ||||
|   youGotMention: "{name}からのメンション" | ||||
|   youGotReply: "{name}からのリプライ" | ||||
|   youGotQuote: "{name}による引用" | ||||
|   youRenoted: "{name}がRenoteしました" | ||||
|   youGotPoll: "{name}が投票しました" | ||||
|   youGotMessagingMessageFromUser: "{name}からのチャットがあります" | ||||
|   youGotMessagingMessageFromGroup: "{name}のチャットがあります" | ||||
|   youWereFollowed: "フォローされました" | ||||
|   youReceivedFollowRequest: "フォローリクエストが来ました" | ||||
|   yourFollowRequestAccepted: "フォローリクエストが承認されました" | ||||
|   youWereInvitedToGroup: "グループに招待されました" | ||||
|  |  | |||
|  | @ -125,6 +125,7 @@ | |||
| 		"css-loader": "3.5.3", | ||||
| 		"cssnano": "4.1.10", | ||||
| 		"dateformat": "3.0.3", | ||||
| 		"deep-entries": "3.1.0", | ||||
| 		"diskusage": "1.1.3", | ||||
| 		"double-ended-queue": "2.1.0-0", | ||||
| 		"escape-regexp": "0.0.1", | ||||
|  | @ -151,6 +152,7 @@ | |||
| 		"http-proxy-agent": "4.0.1", | ||||
| 		"http-signature": "1.3.4", | ||||
| 		"https-proxy-agent": "5.0.0", | ||||
| 		"idb-keyval": "3.2.0", | ||||
| 		"insert-text-at-cursor": "0.3.0", | ||||
| 		"is-root": "2.1.0", | ||||
| 		"is-svg": "4.2.1", | ||||
|  |  | |||
|  | @ -136,15 +136,12 @@ import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, | |||
| import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { ResizeObserver } from '@juggle/resize-observer'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import i18n from './i18n'; | ||||
| import { host, instanceName } from './config'; | ||||
| import { search } from './scripts/search'; | ||||
| 
 | ||||
| const DESKTOP_THRESHOLD = 1100; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XClock: () => import('./components/header-clock.vue').then(m => m.default), | ||||
| 		MkButton: () => import('./components/ui/button.vue').then(m => m.default), | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| type Captcha = { | ||||
| 	render(container: string | Node, options: { | ||||
|  | @ -31,7 +30,6 @@ declare global { | |||
| } | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		provider: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -7,13 +7,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { length } from 'stringz'; | ||||
| import { concat } from '../../prelude/array'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		value: { | ||||
| 			type: Boolean, | ||||
|  |  | |||
|  | @ -15,11 +15,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		items: { | ||||
| 			type: Array, | ||||
|  |  | |||
|  | @ -57,11 +57,8 @@ import MkInput from './ui/input.vue'; | |||
| import MkSelect from './ui/select.vue'; | ||||
| import MkSignin from './signin.vue'; | ||||
| import parseAcct from '../../misc/acct/parse'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkInput, | ||||
|  |  | |||
|  | @ -12,13 +12,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import XDrive from './drive.vue'; | ||||
| import XWindow from './window.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XDrive, | ||||
| 		XWindow, | ||||
|  |  | |||
|  | @ -32,7 +32,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import copyToClipboard from '../scripts/copy-to-clipboard'; | ||||
| //import updateAvatar from '../api/update-avatar'; | ||||
| //import updateBanner from '../api/update-banner'; | ||||
|  | @ -40,8 +39,6 @@ import XFileThumbnail from './drive-file-thumbnail.vue'; | |||
| import { faDownload, faLink, faICursor, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XFileThumbnail | ||||
| 	}, | ||||
|  |  | |||
|  | @ -28,11 +28,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faFolder, faFolderOpen } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		folder: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -15,11 +15,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faCloud } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		folder: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XNavFolder from './drive.nav-folder.vue'; | ||||
| import XFolder from './drive.folder.vue'; | ||||
| import XFile from './drive.file.vue'; | ||||
|  | @ -56,8 +55,6 @@ import XUploader from './uploader.vue'; | |||
| import MkButton from './ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XNavFolder, | ||||
| 		XFolder, | ||||
|  |  | |||
|  | @ -64,7 +64,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { emojilist } from '../../misc/emojilist'; | ||||
| import { getStaticImageUrl } from '../scripts/get-static-image-url'; | ||||
| import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory, faUser } from '@fortawesome/free-solid-svg-icons'; | ||||
|  | @ -73,8 +72,6 @@ import { groupByX } from '../../prelude/array'; | |||
| import XPopup from './popup.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XPopup, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -9,11 +9,9 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -30,12 +30,9 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		user: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -8,10 +8,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faSearch } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: ['q'], | ||||
| 	data() { | ||||
| 		return { | ||||
|  |  | |||
|  | @ -6,12 +6,9 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import XModal from './modal.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XModal, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -125,7 +125,6 @@ | |||
| import Vue from 'vue'; | ||||
| import { faChartBar, faUser, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Chart from 'chart.js'; | ||||
| import i18n from '../i18n'; | ||||
| import MkSelect from './ui/select.vue'; | ||||
| 
 | ||||
| const chartLimit = 90; | ||||
|  | @ -140,8 +139,6 @@ const alpha = (hex, a) => { | |||
| }; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkSelect | ||||
| 	}, | ||||
|  |  | |||
|  | @ -28,10 +28,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		media: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -21,12 +21,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import { getStaticImageUrl } from '../scripts/get-static-image-url'; | ||||
| import ImageViewer from './image-viewer.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		image: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -23,10 +23,8 @@ | |||
| import Vue from 'vue'; | ||||
| import { faPlayCircle } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		video: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -16,12 +16,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| import { host as localHost } from '../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		username: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -93,7 +93,6 @@ import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, f | |||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { parse } from '../../mfm/parse'; | ||||
| import { sum, unique } from '../../prelude/array'; | ||||
| import i18n from '../i18n'; | ||||
| import XSub from './note.sub.vue'; | ||||
| import XNoteHeader from './note-header.vue'; | ||||
| import XNotePreview from './note-preview.vue'; | ||||
|  | @ -109,7 +108,6 @@ import { url } from '../config'; | |||
| import copyToClipboard from '../scripts/copy-to-clipboard'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	 | ||||
| 	components: { | ||||
| 		XSub, | ||||
|  |  | |||
|  | @ -29,15 +29,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import paging from '../scripts/paging'; | ||||
| import XNote from './note.vue'; | ||||
| import XList from './date-separated-list.vue'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XNote, XList, MkButton | ||||
| 	}, | ||||
|  |  | |||
|  | @ -61,13 +61,11 @@ | |||
| import Vue from 'vue'; | ||||
| import { faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faCheck, faPollH } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faClock } from '@fortawesome/free-regular-svg-icons'; | ||||
| import getNoteSummary from '../../misc/get-note-summary'; | ||||
| import noteSummary from '../../misc/get-note-summary'; | ||||
| import XReactionIcon from './reaction-icon.vue'; | ||||
| import MkFollowButton from './follow-button.vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		XReactionIcon, MkFollowButton | ||||
| 	}, | ||||
|  | @ -89,7 +87,7 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			getNoteSummary, | ||||
| 			getNoteSummary: (text: string) => noteSummary(text, this.$root.i18n.messages[this.$root.i18n.locale]), | ||||
| 			followRequestDone: false, | ||||
| 			groupInviteDone: false, | ||||
| 			faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faClock, faCheck, faPollH | ||||
|  |  | |||
|  | @ -18,15 +18,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import paging from '../scripts/paging'; | ||||
| import XNotification from './notification.vue'; | ||||
| import XList from './date-separated-list.vue'; | ||||
| import XNote from './note.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XNotification, | ||||
| 		XList, | ||||
|  |  | |||
|  | @ -8,13 +8,11 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkTextarea from '../ui/textarea.vue'; | ||||
| import MkButton from '../ui/button.vue'; | ||||
| import { apiUrl } from '../../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkTextarea, | ||||
| 		MkButton, | ||||
|  |  | |||
|  | @ -9,14 +9,11 @@ import Vue from 'vue'; | |||
| import { parse } from '@syuilo/aiscript'; | ||||
| import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faHeart } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import XBlock from './page.block.vue'; | ||||
| import { Hpml } from '../../scripts/hpml/evaluator'; | ||||
| import { url } from '../../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XBlock | ||||
| 	}, | ||||
|  |  | |||
|  | @ -51,7 +51,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import { erase } from '../../prelude/array'; | ||||
| import { addTime } from '../../prelude/time'; | ||||
| import { formatDateTimeString } from '../../misc/format-time-string'; | ||||
|  | @ -61,7 +60,6 @@ import MkSwitch from './ui/switch.vue'; | |||
| import MkButton from './ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkInput, | ||||
| 		MkSelect, | ||||
|  |  | |||
|  | @ -24,11 +24,9 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		note: { | ||||
| 			type: Object, | ||||
|  |  | |||
|  | @ -14,15 +14,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import * as XDraggable from 'vuedraggable'; | ||||
| import { faTimesCircle, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { faExclamationTriangle, faICursor } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XFileThumbnail from './drive-file-thumbnail.vue' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XDraggable, | ||||
| 		XFileThumbnail | ||||
|  |  | |||
|  | @ -57,7 +57,6 @@ 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 i18n from '../i18n'; | ||||
| import MkVisibilityChooser from './visibility-chooser.vue'; | ||||
| import MkUserSelect from './user-select.vue'; | ||||
| import XNotePreview from './note-preview.vue'; | ||||
|  | @ -70,8 +69,6 @@ import { formatTimeString } from '../../misc/format-time-string'; | |||
| import { selectDriveFile } from '../scripts/select-drive-file'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XNotePreview, | ||||
| 		XUploader: () => import('./uploader.vue').then(m => m.default), | ||||
|  |  | |||
|  | @ -4,9 +4,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		reaction: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -11,14 +11,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { emojiRegex } from '../../misc/emoji-regex'; | ||||
| import XReactionIcon from './reaction-icon.vue'; | ||||
| import XPopup from './popup.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XPopup, | ||||
| 		XReactionIcon, | ||||
|  |  | |||
|  | @ -20,10 +20,8 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		reaction: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -5,10 +5,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		href: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -7,13 +7,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import XWindow from './window.vue'; | ||||
| import MkSignin from './signin.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkSignin, | ||||
| 		XWindow, | ||||
|  |  | |||
|  | @ -49,13 +49,10 @@ 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'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { apiUrl, host } from '../config'; | ||||
| import { byteify, hexify } from '../scripts/2fa'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkInput, | ||||
|  |  | |||
|  | @ -7,13 +7,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import XWindow from './window.vue'; | ||||
| import XSignup from './signup.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XSignup, | ||||
| 		XWindow, | ||||
|  |  | |||
|  | @ -53,15 +53,12 @@ import Vue 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 i18n from '../i18n'; | ||||
| import { host, url } from '../config'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import MkSwitch from './ui/switch.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkInput, | ||||
|  |  | |||
|  | @ -10,10 +10,8 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			hasDisconnected: false, | ||||
|  |  | |||
|  | @ -21,12 +21,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faReply } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XPoll from './poll.vue'; | ||||
| import XMediaList from './media-list.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		XPoll, | ||||
| 		XMediaList, | ||||
|  |  | |||
|  | @ -8,10 +8,8 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	props: { | ||||
| 		time: { | ||||
| 			type: [Date, String], | ||||
|  |  | |||
|  | @ -21,13 +21,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { apiUrl } from '../config'; | ||||
| //import getMD5 from '../../scripts/get-md5'; | ||||
| import { faSpinner } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			uploads: [], | ||||
|  |  | |||
|  | @ -6,12 +6,9 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import MkUrlPreview from './url-preview.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkUrlPreview | ||||
| 	}, | ||||
|  |  | |||
|  | @ -32,12 +32,9 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faPlayCircle } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import { url as local, lang } from '../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		url: { | ||||
| 			type: String, | ||||
|  |  | |||
|  | @ -31,14 +31,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import paging from '../scripts/paging'; | ||||
| import MkContainer from './ui/container.vue'; | ||||
| import MkFollowButton from './follow-button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkContainer, | ||||
| 		MkFollowButton, | ||||
|  |  | |||
|  | @ -6,15 +6,12 @@ | |||
| import Vue from 'vue'; | ||||
| import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XMenu from './menu.vue'; | ||||
| import copyToClipboard from '../scripts/copy-to-clipboard'; | ||||
| import { host } from '../config'; | ||||
| import getAcct from '../../misc/acct/render'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XMenu | ||||
| 	}, | ||||
|  |  | |||
|  | @ -28,13 +28,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import parseAcct from '../../misc/acct/parse'; | ||||
| import MkFollowButton from './follow-button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkFollowButton | ||||
| 	}, | ||||
|  |  | |||
|  | @ -21,14 +21,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import XWindow from './window.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkInput, | ||||
| 		XWindow, | ||||
|  |  | |||
|  | @ -31,13 +31,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import paging from '../scripts/paging'; | ||||
| import XModal from './modal.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XModal, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -37,11 +37,9 @@ | |||
| import Vue from 'vue'; | ||||
| import { faGlobe, faUnlock, faHome } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faEnvelope } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XPopup from './popup.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		XPopup | ||||
| 	}, | ||||
|  |  | |||
|  | @ -20,12 +20,9 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XModal from './modal.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XModal, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -1,3 +1,6 @@ | |||
| import { clientDb, entries } from './db'; | ||||
| import { fromEntries } from '../prelude/array'; | ||||
| 
 | ||||
| declare const _LANGS_: string[]; | ||||
| declare const _VERSION_: string; | ||||
| declare const _ENV_: string; | ||||
|  | @ -12,7 +15,7 @@ export const apiUrl = url + '/api'; | |||
| export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + '/streaming'; | ||||
| export const lang = localStorage.getItem('lang'); | ||||
| export const langs = _LANGS_; | ||||
| export const locale = JSON.parse(localStorage.getItem('locale')); | ||||
| export const getLocale = async () => fromEntries((await entries(clientDb.i18n)) as [string, string][]); | ||||
| export const version = _VERSION_; | ||||
| export const env = _ENV_; | ||||
| export const instanceName = siteName === 'Misskey' ? null : siteName; | ||||
|  |  | |||
							
								
								
									
										68
									
								
								src/client/db.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/client/db.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| import { Store } from 'idb-keyval'; | ||||
| // Provide functions from idb-keyval
 | ||||
| export { get, set, del, clear, keys } from 'idb-keyval'; | ||||
| 
 | ||||
| //#region Construct DB
 | ||||
| export const clientDb = { | ||||
| 	i18n: new Store('MisskeyClient', 'i18n') | ||||
| }; | ||||
| //#endregion
 | ||||
| 
 | ||||
| //#region Provide some tool functions
 | ||||
| function openTransaction(store: Store, mode: IDBTransactionMode): Promise<IDBTransaction>{ | ||||
| 	return store._dbp.then(db => db.transaction(store.storeName, mode)); | ||||
| } | ||||
| 
 | ||||
| export function entries(store: Store): Promise<[IDBValidKey, unknown][]> { | ||||
| 	const entries: [IDBValidKey, unknown][] = []; | ||||
| 
 | ||||
| 	return store._withIDBStore('readonly', store => { | ||||
| 		store.openCursor().onsuccess = function () { | ||||
| 			if (!this.result) return; | ||||
| 			entries.push([this.result.key, this.result.value]); | ||||
| 			this.result.continue(); | ||||
| 		}; | ||||
| 	}).then(() => entries); | ||||
| } | ||||
| 
 | ||||
| export async function bulkGet(keys: IDBValidKey[], store: Store): Promise<[IDBValidKey, unknown][]> { | ||||
| 	const valPromises: Promise<[IDBValidKey, unknown]>[] = []; | ||||
| 
 | ||||
| 	const tx = await openTransaction(store, 'readwrite'); | ||||
| 	const st = tx.objectStore(store.storeName); | ||||
| 	for (const key of keys) { | ||||
| 		valPromises.push(new Promise((resolve, reject) => { | ||||
| 			const getting = st.get(key); | ||||
| 			getting.onsuccess = function (e) { | ||||
| 				return resolve([key, this.result]); | ||||
| 			}; | ||||
| 			getting.onerror = function (e) { | ||||
| 				return reject(this.error); | ||||
| 			}; | ||||
| 		})); | ||||
| 	} | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		tx.oncomplete = () => resolve(Promise.all(valPromises)); | ||||
| 		tx.abort = tx.onerror = () => reject(tx.error); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| export async function bulkSet(map: [IDBValidKey, any][], store: Store): Promise<void> { | ||||
| 	const tx = await openTransaction(store, 'readwrite'); | ||||
| 	const st = tx.objectStore(store.storeName); | ||||
| 	for (const [key, value] of map) { | ||||
| 		st.put(value, key); | ||||
| 	} | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		tx.oncomplete = () => resolve(); | ||||
| 		tx.abort = tx.onerror = () => reject(tx.error); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| export function count(store: Store): Promise<number> { | ||||
| 	let req: IDBRequest<number>; | ||||
| 	return store._withIDBStore('readonly', store => { | ||||
| 		req = store.count(); | ||||
| 	}).then(() => req.result); | ||||
| } | ||||
| //#endregion
 | ||||
|  | @ -1,12 +0,0 @@ | |||
| import Vue from 'vue'; | ||||
| import VueI18n from 'vue-i18n'; | ||||
| import { lang, locale } from './config'; | ||||
| 
 | ||||
| Vue.use(VueI18n); | ||||
| 
 | ||||
| export default new VueI18n({ | ||||
| 	locale: lang, | ||||
| 	messages: { | ||||
| 		[lang]: locale | ||||
| 	} | ||||
| }); | ||||
|  | @ -7,13 +7,13 @@ import Vuex from 'vuex'; | |||
| import VueMeta from 'vue-meta'; | ||||
| import PortalVue from 'portal-vue'; | ||||
| import VAnimateCss from 'v-animate-css'; | ||||
| import VueI18n from 'vue-i18n'; | ||||
| import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; | ||||
| 
 | ||||
| import i18n from './i18n'; | ||||
| import VueHotkey from './scripts/hotkey'; | ||||
| import App from './app.vue'; | ||||
| import MiOS from './mios'; | ||||
| import { version, langs, instanceName } from './config'; | ||||
| import { version, langs, instanceName, getLocale } from './config'; | ||||
| import PostFormDialog from './components/post-form-dialog.vue'; | ||||
| import Dialog from './components/dialog.vue'; | ||||
| import Menu from './components/menu.vue'; | ||||
|  | @ -21,12 +21,15 @@ import { router } from './router'; | |||
| import { applyTheme, lightTheme } from './theme'; | ||||
| import { isDeviceDarkmode } from './scripts/is-device-darkmode'; | ||||
| import createStore from './store'; | ||||
| import { clientDb, get, count } from './db'; | ||||
| import { setI18nContexts } from './scripts/set-i18n-contexts'; | ||||
| 
 | ||||
| Vue.use(Vuex); | ||||
| Vue.use(VueHotkey); | ||||
| Vue.use(VueMeta); | ||||
| Vue.use(PortalVue); | ||||
| Vue.use(VAnimateCss); | ||||
| Vue.use(VueI18n); | ||||
| Vue.component('fa', FontAwesomeIcon); | ||||
| 
 | ||||
| require('./directives'); | ||||
|  | @ -96,27 +99,6 @@ if (isMobile || window.innerWidth <= 1024) { | |||
| 	head.appendChild(viewport); | ||||
| } | ||||
| 
 | ||||
| //#region Fetch locale data
 | ||||
| const cachedLocale = localStorage.getItem('locale'); | ||||
| 
 | ||||
| if (cachedLocale == null) { | ||||
| 	fetch(`/assets/locales/${lang}.${version}.json`) | ||||
| 		.then(response => response.json()).then(locale => { | ||||
| 			localStorage.setItem('locale', JSON.stringify(locale)); | ||||
| 			i18n.locale = lang; | ||||
| 			i18n.setLocaleMessage(lang, locale); | ||||
| 		}); | ||||
| } else { | ||||
| 	// TODO: 古い時だけ更新
 | ||||
| 	setTimeout(() => { | ||||
| 		fetch(`/assets/locales/${lang}.${version}.json`) | ||||
| 			.then(response => response.json()).then(locale => { | ||||
| 				localStorage.setItem('locale', JSON.stringify(locale)); | ||||
| 			}); | ||||
| 	}, 1000 * 5); | ||||
| } | ||||
| //#endregion
 | ||||
| 
 | ||||
| //#region Set lang attr
 | ||||
| const html = document.documentElement; | ||||
| html.setAttribute('lang', lang); | ||||
|  | @ -167,6 +149,18 @@ os.init(async () => { | |||
| 	}); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	//#region Fetch locale data
 | ||||
| 	const i18n = new VueI18n(); | ||||
| 
 | ||||
| 	await count(clientDb.i18n).then(async n => { | ||||
| 		if (n === 0) return setI18nContexts(lang, version, i18n); | ||||
| 		if ((await get('_version_', clientDb.i18n) !== version)) return setI18nContexts(lang, version, i18n, true); | ||||
| 
 | ||||
| 		i18n.locale = lang; | ||||
| 		i18n.setLocaleMessage(lang, await getLocale()); | ||||
| 	}); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	if ('Notification' in window && store.getters.isSignedIn) { | ||||
| 		// 許可を得ていなかったらリクエスト
 | ||||
| 		if (Notification.permission === 'default') { | ||||
|  | @ -176,6 +170,7 @@ os.init(async () => { | |||
| 
 | ||||
| 	const app = new Vue({ | ||||
| 		store: store, | ||||
| 		i18n, | ||||
| 		metaInfo: { | ||||
| 			title: null, | ||||
| 			titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey') | ||||
|  | @ -183,7 +178,8 @@ os.init(async () => { | |||
| 		data() { | ||||
| 			return { | ||||
| 				stream: os.stream, | ||||
| 				isMobile: isMobile | ||||
| 				isMobile: isMobile, | ||||
| 				i18n // TODO: 消せないか考える SEE: https://github.com/syuilo/misskey/pull/6396#discussion_r429511030
 | ||||
| 			}; | ||||
| 		}, | ||||
| 		methods: { | ||||
|  |  | |||
|  | @ -63,12 +63,9 @@ | |||
| import Vue from 'vue'; | ||||
| import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { version } from '../config'; | ||||
| import i18n from '../i18n'; | ||||
| import MkLink from '../components/link.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkLink | ||||
| 	}, | ||||
|  |  | |||
|  | @ -25,12 +25,9 @@ | |||
| import Vue from 'vue'; | ||||
| import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { version } from '../config'; | ||||
| import i18n from '../i18n'; | ||||
| import MkInstanceStats from '../components/instance-stats.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('instance') as string | ||||
|  |  | |||
|  | @ -21,13 +21,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faCheck, faBroadcastTower } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import MkPagination from '../components/ui/pagination.vue'; | ||||
| import MkButton from '../components/ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('announcements') as string | ||||
|  |  | |||
|  | @ -23,11 +23,9 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import MkButton from '../components/ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkButton | ||||
| 	}, | ||||
|  |  | |||
|  | @ -30,12 +30,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import XForm from './auth.form.vue'; | ||||
| import MkSignin from '../components/signin.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		XForm, | ||||
| 		MkSignin, | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ import Vue from 'vue'; | |||
| import { faFileAlt } from '@fortawesome/free-solid-svg-icons' | ||||
| import MarkdownIt from 'markdown-it'; | ||||
| import MarkdownItAnchor from 'markdown-it-anchor'; | ||||
| import i18n from '../i18n'; | ||||
| import { url, lang } from '../config'; | ||||
| import MkLink from '../components/link.vue'; | ||||
| 
 | ||||
|  | @ -32,8 +31,6 @@ markdown.use(MarkdownItAnchor, { | |||
| }); | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.title, | ||||
|  |  | |||
|  | @ -57,13 +57,10 @@ | |||
| import Vue from 'vue'; | ||||
| import { faChartLine, faPlus, faHashtag, faRocket } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faBookmark, faCommentAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import XUserList from '../components/user-list.vue'; | ||||
| import MkContainer from '../components/ui/container.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('explore') as string | ||||
|  |  | |||
|  | @ -5,11 +5,8 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	created() { | ||||
| 		const acct = new URL(location.href).searchParams.get('acct'); | ||||
| 		if (acct == null) return; | ||||
|  |  | |||
|  | @ -20,12 +20,9 @@ import XSigninDialog from '../components/signin-dialog.vue'; | |||
| import XSignupDialog from '../components/signup-dialog.vue'; | ||||
| import MkButton from '../components/ui/button.vue'; | ||||
| import XNotes from '../components/notes.vue'; | ||||
| import i18n from '../i18n'; | ||||
| import { host } from '../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		XNotes, | ||||
|  |  | |||
|  | @ -25,10 +25,8 @@ import { faLock } from '@fortawesome/free-solid-svg-icons'; | |||
| import MkButton from '../components/ui/button.vue'; | ||||
| import MkInput from '../components/ui/input.vue'; | ||||
| import { host } from '../config'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
|  |  | |||
|  | @ -28,14 +28,11 @@ | |||
| import Vue from 'vue'; | ||||
| import { faBroadcastTower, faPlus } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import MkTextarea from '../../components/ui/textarea.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('announcements') as string | ||||
|  |  | |||
|  | @ -120,7 +120,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import Chart from 'chart.js'; | ||||
| import i18n from '../../i18n'; | ||||
| import { faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown, faMinusCircle, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XWindow from '../../components/window.vue'; | ||||
| import MkUsersDialog from '../../components/users-dialog.vue'; | ||||
|  | @ -141,8 +140,6 @@ const alpha = hex => { | |||
| }; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XWindow, | ||||
| 		MkSelect, | ||||
|  |  | |||
|  | @ -62,7 +62,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faGlobe, faCircle, faExchangeAlt, faCaretDown, faCaretUp, faTrafficLight } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import MkSelect from '../../components/ui/select.vue'; | ||||
|  | @ -70,8 +69,6 @@ import MkPagination from '../../components/ui/pagination.vue'; | |||
| import MkInstanceInfo from './federation.instance.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('federation') as string | ||||
|  |  | |||
|  | @ -107,7 +107,6 @@ import MkButton from '../../components/ui/button.vue'; | |||
| import MkSelect from '../../components/ui/select.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import { version, url } from '../../config'; | ||||
| import i18n from '../../i18n'; | ||||
| 
 | ||||
| const alpha = (hex, a) => { | ||||
| 	const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!; | ||||
|  | @ -118,8 +117,6 @@ const alpha = (hex, a) => { | |||
| }; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('instance') as string | ||||
|  |  | |||
|  | @ -25,7 +25,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import Chart from 'chart.js'; | ||||
| import i18n from '../../i18n'; | ||||
| 
 | ||||
| const alpha = (hex, a) => { | ||||
| 	const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!; | ||||
|  | @ -36,8 +35,6 @@ const alpha = (hex, a) => { | |||
| }; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	props: { | ||||
| 		domain: { | ||||
| 			required: true | ||||
|  |  | |||
|  | @ -21,13 +21,10 @@ | |||
| import Vue from 'vue'; | ||||
| import { faExchangeAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import XQueue from './queue.queue.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: `${this.$t('jobQueue')} | ${this.$t('instance')}` | ||||
|  |  | |||
|  | @ -28,13 +28,10 @@ | |||
| import Vue from 'vue'; | ||||
| import { faPlus, faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('relays') as string | ||||
|  |  | |||
|  | @ -210,12 +210,9 @@ import MkSwitch from '../../components/ui/switch.vue'; | |||
| import MkInfo from '../../components/ui/info.vue'; | ||||
| import MkUserSelect from '../../components/user-select.vue'; | ||||
| import { url } from '../../config'; | ||||
| import i18n from '../../i18n'; | ||||
| import getAcct from '../../../misc/acct/render'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('instance') as string | ||||
|  |  | |||
|  | @ -39,12 +39,9 @@ import { faTimes, faBookmark, faKey, faSync, faMicrophoneSlash, faExternalLinkSq | |||
| import { faSnowflake, faTrashAlt, faBookmark as farBookmark  } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkSwitch from '../../components/ui/switch.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import Progress from '../../scripts/loading'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkSwitch, | ||||
|  |  | |||
|  | @ -42,14 +42,11 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faUser, faUsers, faComments, faPlus } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import getAcct from '../../../misc/acct/render'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkUserSelect from '../../components/user-select.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton | ||||
| 	}, | ||||
|  |  | |||
|  | @ -27,12 +27,10 @@ import Vue from 'vue'; | |||
| import { faPaperPlane, faPhotoVideo, faLaughSquint } from '@fortawesome/free-solid-svg-icons'; | ||||
| import insertTextAtCursor from 'insert-text-at-cursor'; | ||||
| import * as autosize from 'autosize'; | ||||
| import i18n from '../../i18n'; | ||||
| import { formatTimeString } from '../../../misc/format-time-string'; | ||||
| import { selectFile } from '../../scripts/select-file'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		XUploader: () => import('../../components/uploader.vue').then(m => m.default), | ||||
| 	}, | ||||
|  |  | |||
|  | @ -38,13 +38,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import { parse } from '../../../mfm/parse'; | ||||
| import { unique } from '../../../prelude/array'; | ||||
| import MkUrlPreview from '../../components/url-preview.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkUrlPreview | ||||
| 	}, | ||||
|  |  | |||
|  | @ -37,7 +37,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faArrowCircleDown, faFlag, faUsers, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import XList from '../../components/date-separated-list.vue'; | ||||
| import XMessage from './messaging-room.message.vue'; | ||||
| import XForm from './messaging-room.form.vue'; | ||||
|  | @ -45,8 +44,6 @@ import { url } from '../../config'; | |||
| import parseAcct from '../../../misc/acct/parse'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XMessage, | ||||
| 		XForm, | ||||
|  |  | |||
|  | @ -40,12 +40,10 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import i18n from '../i18n'; | ||||
| import MkSignin from '../components/signin.vue'; | ||||
| import MkButton from '../components/ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkSignin, | ||||
| 		MkButton, | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import MkTextarea from '../../components/ui/textarea.vue'; | ||||
|  | @ -58,8 +57,6 @@ import MkUserSelect from '../../components/user-select.vue'; | |||
| import getAcct from '../../../misc/acct/render'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, MkInput, MkTextarea, MkSelect, MkSwitch | ||||
| 	}, | ||||
|  |  | |||
|  | @ -41,14 +41,11 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faTimes, faUsers } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import Progress from '../../scripts/loading'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkUserSelect from '../../components/user-select.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.group ? `${this.group.name} | ${this.$t('manageGroups')}` : this.$t('manageGroups') | ||||
|  |  | |||
|  | @ -40,14 +40,11 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faTimes, faListUl } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import Progress from '../../scripts/loading'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkUserSelect from '../../components/user-select.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.list ? `${this.list.name} | ${this.$t('manageLists')}` : this.$t('manageLists') | ||||
|  |  | |||
|  | @ -65,7 +65,6 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faLock } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import { hostname } from '../../config'; | ||||
| import { byteify, hexify, stringify } from '../../scripts/2fa'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
|  | @ -74,7 +73,6 @@ import MkInput from '../../components/ui/input.vue'; | |||
| import MkSwitch from '../../components/ui/switch.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkButton, MkInfo, MkInput, MkSwitch | ||||
| 	}, | ||||
|  |  | |||
|  | @ -13,12 +13,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faKey, faSyncAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkInput from '../../components/ui/input.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	components: { | ||||
| 		MkButton, MkInput | ||||
| 	}, | ||||
|  |  | |||
|  | @ -13,12 +13,9 @@ import Vue from 'vue'; | |||
| import { faCloud, faFolderOpen } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faClock, faEyeSlash, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import { selectDriveFolder } from '../../scripts/select-drive-folder'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -21,12 +21,9 @@ import Vue from 'vue'; | |||
| import { faDownload, faUpload, faBoxes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkSelect from '../../components/ui/select.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import { apiUrl } from '../../config'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkSelect, | ||||
|  |  | |||
|  | @ -29,13 +29,10 @@ | |||
| import Vue from 'vue'; | ||||
| import { faShareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons'; | ||||
| import i18n from '../../i18n'; | ||||
| import { apiUrl } from '../../config'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton | ||||
| 	}, | ||||
|  |  | |||
|  | @ -34,11 +34,8 @@ | |||
| import Vue from 'vue'; | ||||
| import { faBan } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkPagination from '../../components/ui/pagination.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkPagination, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -24,11 +24,8 @@ import Vue from 'vue'; | |||
| import { faLock } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkSelect from '../../components/ui/select.vue'; | ||||
| import MkSwitch from '../../components/ui/switch.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkSelect, | ||||
| 		MkSwitch, | ||||
|  |  | |||
|  | @ -62,13 +62,10 @@ import MkButton from '../../components/ui/button.vue'; | |||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import MkTextarea from '../../components/ui/textarea.vue'; | ||||
| import MkSwitch from '../../components/ui/switch.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import { host } from '../../config'; | ||||
| import { selectFile } from '../../scripts/select-file'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		MkInput, | ||||
|  |  | |||
|  | @ -21,13 +21,10 @@ import { faUndo } from '@fortawesome/free-solid-svg-icons'; | |||
| import MkInput from '../../components/ui/input.vue'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import MkReactionPicker from '../../components/reaction-picker.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| import { emojiRegexWithCustom } from '../../../misc/emoji-regex'; | ||||
| import { defaultSettings } from '../../store'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkInput, | ||||
| 		MkButton, | ||||
|  |  | |||
|  | @ -11,11 +11,8 @@ | |||
| import Vue from 'vue'; | ||||
| import { faLock } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '../../components/ui/button.vue'; | ||||
| import i18n from '../../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
|  |  | |||
|  | @ -15,11 +15,8 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('notFound') as string | ||||
|  |  | |||
|  | @ -29,14 +29,12 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../i18n'; | ||||
| import Progress from '../scripts/loading'; | ||||
| import XNote from '../components/note.vue'; | ||||
| import XNotes from '../components/notes.vue'; | ||||
| import MkRemoteCaution from '../components/remote-caution.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 	metaInfo() { | ||||
| 		return { | ||||
| 			title: this.$t('note') as string | ||||
|  |  | |||
|  | @ -40,15 +40,12 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faBolt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../../i18n'; | ||||
| import XContainer from '../page-editor.container.vue'; | ||||
| import MkSelect from '../../../components/ui/select.vue'; | ||||
| import MkInput from '../../../components/ui/input.vue'; | ||||
| import MkSwitch from '../../../components/ui/switch.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XContainer, MkSelect, MkInput, MkSwitch | ||||
| 	}, | ||||
|  |  | |||
|  | @ -13,13 +13,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faPaintBrush, faMagic } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../../i18n'; | ||||
| import XContainer from '../page-editor.container.vue'; | ||||
| import MkInput from '../../../components/ui/input.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XContainer, MkInput | ||||
| 	}, | ||||
|  |  | |||
|  | @ -13,13 +13,10 @@ | |||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; | ||||
| import i18n from '../../../i18n'; | ||||
| import XContainer from '../page-editor.container.vue'; | ||||
| import MkInput from '../../../components/ui/input.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	i18n, | ||||
| 
 | ||||
| 	components: { | ||||
| 		XContainer, MkInput | ||||
| 	}, | ||||
|  |  | |||
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