From 0c2b79acedc08fa0702b52d612aa0b92f67f1573 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 7 Feb 2018 15:16:01 +0900 Subject: wip --- src/web/app/dev/tags/new-app-form.tag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/web/app/dev') diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag index fdd442a836..c9518d8deb 100644 --- a/src/web/app/dev/tags/new-app-form.tag +++ b/src/web/app/dev/tags/new-app-form.tag @@ -73,7 +73,7 @@

%fa:exclamation-triangle%アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。

- + diff --git a/src/web/app/desktop/tags/repost-form-window.tag b/src/web/app/desktop/tags/repost-form-window.tag index dbc3f5a3c5..939ff4e383 100644 --- a/src/web/app/desktop/tags/repost-form-window.tag +++ b/src/web/app/desktop/tags/repost-form-window.tag @@ -19,23 +19,23 @@ this.onDocumentKeydown = e => { if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') { if (e.which == 27) { // Esc - this.refs.window.close(); + this.$refs.window.close(); } } }; this.on('mount', () => { - this.refs.window.refs.form.on('cancel', () => { - this.refs.window.close(); + this.$refs.window.refs.form.on('cancel', () => { + this.$refs.window.close(); }); - this.refs.window.refs.form.on('posted', () => { - this.refs.window.close(); + this.$refs.window.refs.form.on('posted', () => { + this.$refs.window.close(); }); document.addEventListener('keydown', this.onDocumentKeydown); - this.refs.window.on('closed', () => { + this.$refs.window.on('closed', () => { this.unmount(); }); }); diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag index 946871765b..b2ebbf4c46 100644 --- a/src/web/app/desktop/tags/repost-form.tag +++ b/src/web/app/desktop/tags/repost-form.tag @@ -117,11 +117,11 @@ quote: true }); - this.refs.form.on('post', () => { + this.$refs.form.on('post', () => { this.trigger('posted'); }); - this.refs.form.focus(); + this.$refs.form.focus(); }; diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag index f7ec85a4fe..0c8dbcbf63 100644 --- a/src/web/app/desktop/tags/search-posts.tag +++ b/src/web/app/desktop/tags/search-posts.tag @@ -53,7 +53,7 @@ isLoading: false, isEmpty: posts.length == 0 }); - this.refs.timeline.setPosts(posts); + this.$refs.timeline.setPosts(posts); this.trigger('loaded'); }); }); @@ -66,7 +66,7 @@ this.onDocumentKeydown = e => { if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') { if (e.which == 84) { // t - this.refs.timeline.focus(); + this.$refs.timeline.focus(); } } }; @@ -84,7 +84,7 @@ this.update({ moreLoading: false }); - this.refs.timeline.prependPosts(posts); + this.$refs.timeline.prependPosts(posts); }); }; diff --git a/src/web/app/desktop/tags/search.tag b/src/web/app/desktop/tags/search.tag index d5159fe4e9..e29a2b2737 100644 --- a/src/web/app/desktop/tags/search.tag +++ b/src/web/app/desktop/tags/search.tag @@ -26,7 +26,7 @@ this.query = this.opts.query; this.on('mount', () => { - this.refs.posts.on('loaded', () => { + this.$refs.posts.on('loaded', () => { this.trigger('loaded'); }); }); diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag index 6225145589..6d1e59413d 100644 --- a/src/web/app/desktop/tags/select-file-from-drive-window.tag +++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag @@ -141,33 +141,33 @@ this.title = this.opts.title || '%fa:R file%ファイルを選択'; this.on('mount', () => { - this.refs.window.refs.browser.on('selected', file => { + this.$refs.window.refs.browser.on('selected', file => { this.files = [file]; this.ok(); }); - this.refs.window.refs.browser.on('change-selection', files => { + this.$refs.window.refs.browser.on('change-selection', files => { this.update({ files: files }); }); - this.refs.window.on('closed', () => { + this.$refs.window.on('closed', () => { this.unmount(); }); }); this.close = () => { - this.refs.window.close(); + this.$refs.window.close(); }; this.upload = () => { - this.refs.window.refs.browser.selectLocalFile(); + this.$refs.window.refs.browser.selectLocalFile(); }; this.ok = () => { this.trigger('selected', this.multiple ? this.files : this.files[0]); - this.refs.window.close(); + this.$refs.window.close(); }; diff --git a/src/web/app/desktop/tags/select-folder-from-drive-window.tag b/src/web/app/desktop/tags/select-folder-from-drive-window.tag index 45700420cc..7bfe5af357 100644 --- a/src/web/app/desktop/tags/select-folder-from-drive-window.tag +++ b/src/web/app/desktop/tags/select-folder-from-drive-window.tag @@ -95,18 +95,18 @@ this.title = this.opts.title || '%fa:R folder%フォルダを選択'; this.on('mount', () => { - this.refs.window.on('closed', () => { + this.$refs.window.on('closed', () => { this.unmount(); }); }); this.close = () => { - this.refs.window.close(); + this.$refs.window.close(); }; this.ok = () => { - this.trigger('selected', this.refs.window.refs.browser.folder); - this.refs.window.close(); + this.trigger('selected', this.$refs.window.refs.browser.folder); + this.$refs.window.close(); }; diff --git a/src/web/app/desktop/tags/settings-window.tag b/src/web/app/desktop/tags/settings-window.tag index 5a725af51e..e68a44a4f6 100644 --- a/src/web/app/desktop/tags/settings-window.tag +++ b/src/web/app/desktop/tags/settings-window.tag @@ -18,13 +18,13 @@ diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index efc5da83f1..084bde0095 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -179,10 +179,10 @@ this.updateAccount = () => { this.api('i/update', { - name: this.refs.accountName.value, - location: this.refs.accountLocation.value || null, - description: this.refs.accountDescription.value || null, - birthday: this.refs.accountBirthday.value || null + name: this.$refs.accountName.value, + location: this.$refs.accountLocation.value || null, + description: this.$refs.accountDescription.value || null, + birthday: this.$refs.accountBirthday.value || null }).then(() => { notify('プロフィールを更新しました'); }); @@ -320,7 +320,7 @@ this.submit = () => { this.api('i/2fa/done', { - token: this.refs.token.value + token: this.$refs.token.value }).then(() => { notify('%i18n:desktop.tags.mk-2fa-setting.success%'); this.I.two_factor_enabled = true; diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag index 1a81b545b6..01e1fdb31e 100644 --- a/src/web/app/desktop/tags/sub-post-content.tag +++ b/src/web/app/desktop/tags/sub-post-content.tag @@ -43,9 +43,9 @@ this.on('mount', () => { if (this.post.text) { const tokens = this.post.ast; - this.refs.text.innerHTML = compile(tokens, false); + this.$refs.text.innerHTML = compile(tokens, false); - Array.from(this.refs.text.children).forEach(e => { + Array.from(this.$refs.text.children).forEach(e => { if (e.tagName == 'MK-URL') riot.mount(e); }); } diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag index 0616a95f99..115b22c862 100644 --- a/src/web/app/desktop/tags/timeline.tag +++ b/src/web/app/desktop/tags/timeline.tag @@ -437,10 +437,10 @@ this.refresh = post => { this.set(post); this.update(); - if (this.refs.reactionsViewer) this.refs.reactionsViewer.update({ + if (this.$refs.reactionsViewer) this.$refs.reactionsViewer.update({ post }); - if (this.refs.pollViewer) this.refs.pollViewer.init(post); + if (this.$refs.pollViewer) this.$refs.pollViewer.init(post); }; this.onStreamPostUpdated = data => { @@ -484,9 +484,9 @@ if (this.p.text) { const tokens = this.p.ast; - this.refs.text.innerHTML = this.refs.text.innerHTML.replace('

', compile(tokens)); + this.$refs.text.innerHTML = this.$refs.text.innerHTML.replace('

', compile(tokens)); - Array.from(this.refs.text.children).forEach(e => { + Array.from(this.$refs.text.children).forEach(e => { if (e.tagName == 'MK-URL') riot.mount(e); }); @@ -494,7 +494,7 @@ tokens .filter(t => (t.type == 'url' || t.type == 'link') && !t.silent) .map(t => { - riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), { + riot.mount(this.$refs.text.appendChild(document.createElement('mk-url-preview')), { url: t.url }); }); @@ -521,14 +521,14 @@ this.react = () => { riot.mount(document.body.appendChild(document.createElement('mk-reaction-picker')), { - source: this.refs.reactButton, + source: this.$refs.reactButton, post: this.p }); }; this.menu = () => { riot.mount(document.body.appendChild(document.createElement('mk-post-menu')), { - source: this.refs.menuButton, + source: this.$refs.menuButton, post: this.p }); }; diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag index 3e7b5c2eca..777624d7ba 100644 --- a/src/web/app/desktop/tags/ui.tag +++ b/src/web/app/desktop/tags/ui.tag @@ -180,7 +180,7 @@ this.onsubmit = e => { e.preventDefault(); - this.page('/search?q=' + encodeURIComponent(this.refs.q.value)); + this.page('/search?q=' + encodeURIComponent(this.$refs.q.value)); }; diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag index 19ee2f3284..0bfad05c27 100644 --- a/src/web/app/desktop/tags/user-timeline.tag +++ b/src/web/app/desktop/tags/user-timeline.tag @@ -88,7 +88,7 @@ this.onDocumentKeydown = e => { if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') { if (e.which == 84) { // [t] - this.refs.timeline.focus(); + this.$refs.timeline.focus(); } } }; @@ -103,25 +103,25 @@ isLoading: false, isEmpty: posts.length == 0 }); - this.refs.timeline.setPosts(posts); + this.$refs.timeline.setPosts(posts); if (cb) cb(); }); }; this.more = () => { - if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return; + if (this.moreLoading || this.isLoading || this.$refs.timeline.posts.length == 0) return; this.update({ moreLoading: true }); this.api('users/posts', { user_id: this.user.id, with_replies: this.mode == 'with-replies', - until_id: this.refs.timeline.tail().id + until_id: this.$refs.timeline.tail().id }).then(posts => { this.update({ moreLoading: false }); - this.refs.timeline.prependPosts(posts); + this.$refs.timeline.prependPosts(posts); }); }; diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag index 5dc4175cf9..8eca3caaa3 100644 --- a/src/web/app/desktop/tags/user.tag +++ b/src/web/app/desktop/tags/user.tag @@ -206,10 +206,10 @@ const z = 1.25; // 奥行き(小さいほど奥) const pos = -(top / z); - this.refs.banner.style.backgroundPosition = `center calc(50% - ${pos}px)`; + this.$refs.banner.style.backgroundPosition = `center calc(50% - ${pos}px)`; const blur = top / 32 - if (blur <= 10) this.refs.banner.style.filter = `blur(${blur}px)`; + if (blur <= 10) this.$refs.banner.style.filter = `blur(${blur}px)`; }; this.onUpdateBanner = () => { @@ -715,12 +715,12 @@ this.user = this.opts.user; this.on('mount', () => { - this.refs.tl.on('loaded', () => { + this.$refs.tl.on('loaded', () => { this.trigger('loaded'); }); - this.scrollFollowerLeft = new ScrollFollower(this.refs.left, this.parent.root.getBoundingClientRect().top); - this.scrollFollowerRight = new ScrollFollower(this.refs.right, this.parent.root.getBoundingClientRect().top); + this.scrollFollowerLeft = new ScrollFollower(this.$refs.left, this.parent.root.getBoundingClientRect().top); + this.scrollFollowerRight = new ScrollFollower(this.$refs.right, this.parent.root.getBoundingClientRect().top); }); this.on('unmount', () => { @@ -729,7 +729,7 @@ }); this.warp = date => { - this.refs.tl.warp(date); + this.$refs.tl.warp(date); }; diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag index ebc7382d5a..31830d9078 100644 --- a/src/web/app/desktop/tags/window.tag +++ b/src/web/app/desktop/tags/window.tag @@ -199,13 +199,13 @@ this.canResize = !this.isFlexible; this.on('mount', () => { - this.refs.main.style.width = this.opts.width || '530px'; - this.refs.main.style.height = this.opts.height || 'auto'; + this.$refs.main.style.width = this.opts.width || '530px'; + this.$refs.main.style.height = this.opts.height || 'auto'; - this.refs.main.style.top = '15%'; - this.refs.main.style.left = (window.innerWidth / 2) - (this.refs.main.offsetWidth / 2) + 'px'; + this.$refs.main.style.top = '15%'; + this.$refs.main.style.left = (window.innerWidth / 2) - (this.$refs.main.offsetWidth / 2) + 'px'; - this.refs.header.addEventListener('contextmenu', e => { + this.$refs.header.addEventListener('contextmenu', e => { e.preventDefault(); }); @@ -219,15 +219,15 @@ }); this.onBrowserResize = () => { - const position = this.refs.main.getBoundingClientRect(); + const position = this.$refs.main.getBoundingClientRect(); const browserWidth = window.innerWidth; const browserHeight = window.innerHeight; - const windowWidth = this.refs.main.offsetWidth; - const windowHeight = this.refs.main.offsetHeight; - if (position.left < 0) this.refs.main.style.left = 0; - if (position.top < 0) this.refs.main.style.top = 0; - if (position.left + windowWidth > browserWidth) this.refs.main.style.left = browserWidth - windowWidth + 'px'; - if (position.top + windowHeight > browserHeight) this.refs.main.style.top = browserHeight - windowHeight + 'px'; + const windowWidth = this.$refs.main.offsetWidth; + const windowHeight = this.$refs.main.offsetHeight; + if (position.left < 0) this.$refs.main.style.left = 0; + if (position.top < 0) this.$refs.main.style.top = 0; + if (position.left + windowWidth > browserWidth) this.$refs.main.style.left = browserWidth - windowWidth + 'px'; + if (position.top + windowHeight > browserHeight) this.$refs.main.style.top = browserHeight - windowHeight + 'px'; }; this.open = () => { @@ -236,25 +236,25 @@ this.top(); if (this.isModal) { - this.refs.bg.style.pointerEvents = 'auto'; + this.$refs.bg.style.pointerEvents = 'auto'; anime({ - targets: this.refs.bg, + targets: this.$refs.bg, opacity: 1, duration: 100, easing: 'linear' }); } - this.refs.main.style.pointerEvents = 'auto'; + this.$refs.main.style.pointerEvents = 'auto'; anime({ - targets: this.refs.main, + targets: this.$refs.main, opacity: 1, scale: [1.1, 1], duration: 200, easing: 'easeOutQuad' }); - //this.refs.main.focus(); + //this.$refs.main.focus(); setTimeout(() => { this.trigger('opened'); @@ -262,10 +262,10 @@ }; this.popout = () => { - const position = this.refs.main.getBoundingClientRect(); + const position = this.$refs.main.getBoundingClientRect(); - const width = parseInt(getComputedStyle(this.refs.main, '').width, 10); - const height = parseInt(getComputedStyle(this.refs.main, '').height, 10); + const width = parseInt(getComputedStyle(this.$refs.main, '').width, 10); + const height = parseInt(getComputedStyle(this.$refs.main, '').height, 10); const x = window.screenX + position.left; const y = window.screenY + position.top; @@ -281,19 +281,19 @@ this.trigger('closing'); if (this.isModal) { - this.refs.bg.style.pointerEvents = 'none'; + this.$refs.bg.style.pointerEvents = 'none'; anime({ - targets: this.refs.bg, + targets: this.$refs.bg, opacity: 0, duration: 300, easing: 'linear' }); } - this.refs.main.style.pointerEvents = 'none'; + this.$refs.main.style.pointerEvents = 'none'; anime({ - targets: this.refs.main, + targets: this.$refs.main, opacity: 0, scale: 0.8, duration: 300, @@ -318,8 +318,8 @@ }); if (z > 0) { - this.refs.main.style.zIndex = z + 1; - if (this.isModal) this.refs.bg.style.zIndex = z + 1; + this.$refs.main.style.zIndex = z + 1; + if (this.isModal) this.$refs.bg.style.zIndex = z + 1; } }; @@ -340,9 +340,9 @@ this.onHeaderMousedown = e => { e.preventDefault(); - if (!contains(this.refs.main, document.activeElement)) this.refs.main.focus(); + if (!contains(this.$refs.main, document.activeElement)) this.$refs.main.focus(); - const position = this.refs.main.getBoundingClientRect(); + const position = this.$refs.main.getBoundingClientRect(); const clickX = e.clientX; const clickY = e.clientY; @@ -350,8 +350,8 @@ const moveBaseY = clickY - position.top; const browserWidth = window.innerWidth; const browserHeight = window.innerHeight; - const windowWidth = this.refs.main.offsetWidth; - const windowHeight = this.refs.main.offsetHeight; + const windowWidth = this.$refs.main.offsetWidth; + const windowHeight = this.$refs.main.offsetHeight; // 動かした時 dragListen(me => { @@ -370,8 +370,8 @@ // 右はみ出し if (moveLeft + windowWidth > browserWidth) moveLeft = browserWidth - windowWidth; - this.refs.main.style.left = moveLeft + 'px'; - this.refs.main.style.top = moveTop + 'px'; + this.$refs.main.style.left = moveLeft + 'px'; + this.$refs.main.style.top = moveTop + 'px'; }); }; @@ -380,8 +380,8 @@ e.preventDefault(); const base = e.clientY; - const height = parseInt(getComputedStyle(this.refs.main, '').height, 10); - const top = parseInt(getComputedStyle(this.refs.main, '').top, 10); + const height = parseInt(getComputedStyle(this.$refs.main, '').height, 10); + const top = parseInt(getComputedStyle(this.$refs.main, '').top, 10); // 動かした時 dragListen(me => { @@ -406,8 +406,8 @@ e.preventDefault(); const base = e.clientX; - const width = parseInt(getComputedStyle(this.refs.main, '').width, 10); - const left = parseInt(getComputedStyle(this.refs.main, '').left, 10); + const width = parseInt(getComputedStyle(this.$refs.main, '').width, 10); + const left = parseInt(getComputedStyle(this.$refs.main, '').left, 10); const browserWidth = window.innerWidth; // 動かした時 @@ -430,8 +430,8 @@ e.preventDefault(); const base = e.clientY; - const height = parseInt(getComputedStyle(this.refs.main, '').height, 10); - const top = parseInt(getComputedStyle(this.refs.main, '').top, 10); + const height = parseInt(getComputedStyle(this.$refs.main, '').height, 10); + const top = parseInt(getComputedStyle(this.$refs.main, '').top, 10); const browserHeight = window.innerHeight; // 動かした時 @@ -454,8 +454,8 @@ e.preventDefault(); const base = e.clientX; - const width = parseInt(getComputedStyle(this.refs.main, '').width, 10); - const left = parseInt(getComputedStyle(this.refs.main, '').left, 10); + const width = parseInt(getComputedStyle(this.$refs.main, '').width, 10); + const left = parseInt(getComputedStyle(this.$refs.main, '').left, 10); // 動かした時 dragListen(me => { @@ -501,22 +501,22 @@ // 高さを適用 this.applyTransformHeight = height => { - this.refs.main.style.height = height + 'px'; + this.$refs.main.style.height = height + 'px'; }; // 幅を適用 this.applyTransformWidth = width => { - this.refs.main.style.width = width + 'px'; + this.$refs.main.style.width = width + 'px'; }; // Y座標を適用 this.applyTransformTop = top => { - this.refs.main.style.top = top + 'px'; + this.$refs.main.style.top = top + 'px'; }; // X座標を適用 this.applyTransformLeft = left => { - this.refs.main.style.left = left + 'px'; + this.$refs.main.style.left = left + 'px'; }; function dragListen(fn) { diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag index c9518d8deb..aba6b1524f 100644 --- a/src/web/app/dev/tags/new-app-form.tag +++ b/src/web/app/dev/tags/new-app-form.tag @@ -183,7 +183,7 @@ this.nidState = null; this.onChangeNid = () => { - const nid = this.refs.nid.value; + const nid = this.$refs.nid.value; if (nid == '') { this.update({ @@ -223,13 +223,13 @@ }; this.onsubmit = () => { - const name = this.refs.name.value; - const nid = this.refs.nid.value; - const description = this.refs.description.value; - const cb = this.refs.cb.value; + const name = this.$refs.name.value; + const nid = this.$refs.nid.value; + const description = this.$refs.description.value; + const cb = this.$refs.cb.value; const permission = []; - this.refs.permission.querySelectorAll('input').forEach(el => { + this.$refs.permission.querySelectorAll('input').forEach(el => { if (el.checked) permission.push(el.value); }); diff --git a/src/web/app/mobile/tags/drive-folder-selector.tag b/src/web/app/mobile/tags/drive-folder-selector.tag index 82e22fed29..37d571d731 100644 --- a/src/web/app/mobile/tags/drive-folder-selector.tag +++ b/src/web/app/mobile/tags/drive-folder-selector.tag @@ -62,7 +62,7 @@ }; this.ok = () => { - this.trigger('selected', this.refs.browser.folder); + this.trigger('selected', this.$refs.browser.folder); this.unmount(); }; diff --git a/src/web/app/mobile/tags/drive-selector.tag b/src/web/app/mobile/tags/drive-selector.tag index 36fed8c327..ab67cc80c0 100644 --- a/src/web/app/mobile/tags/drive-selector.tag +++ b/src/web/app/mobile/tags/drive-selector.tag @@ -63,13 +63,13 @@ this.files = []; this.on('mount', () => { - this.refs.browser.on('change-selection', files => { + this.$refs.browser.on('change-selection', files => { this.update({ files: files }); }); - this.refs.browser.on('selected', file => { + this.$refs.browser.on('selected', file => { this.trigger('selected', file); this.unmount(); }); diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag index d3ca1aff90..3d0396692d 100644 --- a/src/web/app/mobile/tags/drive.tag +++ b/src/web/app/mobile/tags/drive.tag @@ -209,7 +209,7 @@ } if (this.opts.isNaked) { - this.refs.nav.style.top = `${this.opts.top}px`; + this.$refs.nav.style.top = `${this.opts.top}px`; } }); @@ -517,7 +517,7 @@ }; this.selectLocalFile = () => { - this.refs.file.click(); + this.$refs.file.click(); }; this.createFolder = () => { @@ -574,7 +574,7 @@ }; this.changeLocalFile = () => { - Array.from(this.refs.file.files).forEach(f => this.refs.uploader.upload(f, this.folder)); + Array.from(this.$refs.file.files).forEach(f => this.$refs.uploader.upload(f, this.folder)); }; diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag index 2d9338fd35..82fbb6609e 100644 --- a/src/web/app/mobile/tags/drive/file-viewer.tag +++ b/src/web/app/mobile/tags/drive/file-viewer.tag @@ -243,7 +243,7 @@ this.onImageLoaded = () => { const self = this; - EXIF.getData(this.refs.img, function() { + EXIF.getData(this.$refs.img, function() { const allMetaData = EXIF.getAllTags(this); self.update({ exif: allMetaData diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag index 397d2b3980..aa3818007b 100644 --- a/src/web/app/mobile/tags/home-timeline.tag +++ b/src/web/app/mobile/tags/home-timeline.tag @@ -28,7 +28,7 @@ this.fetch = () => { this.api('posts/timeline').then(posts => { - this.refs.timeline.setPosts(posts); + this.$refs.timeline.setPosts(posts); }); }; @@ -47,7 +47,7 @@ this.more = () => { return this.api('posts/timeline', { - until_id: this.refs.timeline.tail().id + until_id: this.$refs.timeline.tail().id }); }; @@ -55,7 +55,7 @@ this.update({ isEmpty: false }); - this.refs.timeline.addPost(post); + this.$refs.timeline.addPost(post); }; this.onStreamFollow = () => { diff --git a/src/web/app/mobile/tags/home.tag b/src/web/app/mobile/tags/home.tag index d92e3ae4e5..2c07c286d2 100644 --- a/src/web/app/mobile/tags/home.tag +++ b/src/web/app/mobile/tags/home.tag @@ -15,7 +15,7 @@ diff --git a/src/web/app/mobile/tags/search.tag b/src/web/app/mobile/tags/search.tag index 2d299e0a77..15a861d7a5 100644 --- a/src/web/app/mobile/tags/search.tag +++ b/src/web/app/mobile/tags/search.tag @@ -8,7 +8,7 @@ this.query = this.opts.query; this.on('mount', () => { - this.refs.posts.on('loaded', () => { + this.$refs.posts.on('loaded', () => { this.trigger('loaded'); }); }); diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag index adeb84dea0..7192cd0130 100644 --- a/src/web/app/mobile/tags/sub-post-content.tag +++ b/src/web/app/mobile/tags/sub-post-content.tag @@ -35,9 +35,9 @@ this.on('mount', () => { if (this.post.text) { const tokens = this.post.ast; - this.refs.text.innerHTML = compile(tokens, false); + this.$refs.text.innerHTML = compile(tokens, false); - Array.from(this.refs.text.children).forEach(e => { + Array.from(this.$refs.text.children).forEach(e => { if (e.tagName == 'MK-URL') riot.mount(e); }); } diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag index 400fa5d85f..66f58ff0af 100644 --- a/src/web/app/mobile/tags/timeline.tag +++ b/src/web/app/mobile/tags/timeline.tag @@ -482,10 +482,10 @@ this.refresh = post => { this.set(post); this.update(); - if (this.refs.reactionsViewer) this.refs.reactionsViewer.update({ + if (this.$refs.reactionsViewer) this.$refs.reactionsViewer.update({ post }); - if (this.refs.pollViewer) this.refs.pollViewer.init(post); + if (this.$refs.pollViewer) this.$refs.pollViewer.init(post); }; this.onStreamPostUpdated = data => { @@ -529,9 +529,9 @@ if (this.p.text) { const tokens = this.p.ast; - this.refs.text.innerHTML = this.refs.text.innerHTML.replace('

', compile(tokens)); + this.$refs.text.innerHTML = this.$refs.text.innerHTML.replace('

', compile(tokens)); - Array.from(this.refs.text.children).forEach(e => { + Array.from(this.$refs.text.children).forEach(e => { if (e.tagName == 'MK-URL') riot.mount(e); }); @@ -539,7 +539,7 @@ tokens .filter(t => (t.type == 'url' || t.type == 'link') && !t.silent) .map(t => { - riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), { + riot.mount(this.$refs.text.appendChild(document.createElement('mk-url-preview')), { url: t.url }); }); @@ -569,7 +569,7 @@ this.react = () => { riot.mount(document.body.appendChild(document.createElement('mk-reaction-picker')), { - source: this.refs.reactButton, + source: this.$refs.reactButton, post: this.p, compact: true }); @@ -577,7 +577,7 @@ this.menu = () => { riot.mount(document.body.appendChild(document.createElement('mk-post-menu')), { - source: this.refs.menuButton, + source: this.$refs.menuButton, post: this.p, compact: true }); diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index b03534f925..c5dc4b2e4e 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -30,7 +30,7 @@ this.toggleDrawer = () => { this.isDrawerOpening = !this.isDrawerOpening; - this.refs.nav.root.style.display = this.isDrawerOpening ? 'block' : 'none'; + this.$refs.nav.root.style.display = this.isDrawerOpening ? 'block' : 'none'; }; this.onStreamNotification = notification => { @@ -209,7 +209,7 @@ }; this.setTitle = title => { - this.refs.title.innerHTML = title; + this.$refs.title.innerHTML = title; }; this.setFunc = (fn, icon) => { diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag index b710e376c6..c4cdedba81 100644 --- a/src/web/app/mobile/tags/user-followers.tag +++ b/src/web/app/mobile/tags/user-followers.tag @@ -20,7 +20,7 @@ }; this.on('mount', () => { - this.refs.list.on('loaded', () => { + this.$refs.list.on('loaded', () => { this.trigger('loaded'); }); }); diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag index 62ca091812..3a6a54dd76 100644 --- a/src/web/app/mobile/tags/user-following.tag +++ b/src/web/app/mobile/tags/user-following.tag @@ -20,7 +20,7 @@ }; this.on('mount', () => { - this.refs.list.on('loaded', () => { + this.$refs.list.on('loaded', () => { this.trigger('loaded'); }); }); diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag index 86ead5971f..65203fec4b 100644 --- a/src/web/app/mobile/tags/user-timeline.tag +++ b/src/web/app/mobile/tags/user-timeline.tag @@ -26,7 +26,7 @@ return this.api('users/posts', { user_id: this.user.id, with_media: this.withMedia, - until_id: this.refs.timeline.tail().id + until_id: this.$refs.timeline.tail().id }); }; diff --git a/src/web/app/status/tags/index.tag b/src/web/app/status/tags/index.tag index dcadc66172..198aa89e38 100644 --- a/src/web/app/status/tags/index.tag +++ b/src/web/app/status/tags/index.tag @@ -93,7 +93,7 @@ }); this.onStats = stats => { - this.refs.chart.addData(1 - stats.cpu_usage); + this.$refs.chart.addData(1 - stats.cpu_usage); const percentage = (stats.cpu_usage * 100).toFixed(0); @@ -124,7 +124,7 @@ this.onStats = stats => { stats.mem.used = stats.mem.total - stats.mem.free; - this.refs.chart.addData(1 - (stats.mem.used / stats.mem.total)); + this.$refs.chart.addData(1 - (stats.mem.used / stats.mem.total)); const percentage = (stats.mem.used / stats.mem.total * 100).toFixed(0); -- cgit v1.2.3-freya From 063193f429f5a8a9843fe1f13696c9d22a261b9e Mon Sep 17 00:00:00 2001 From: こぴなたみぽ Date: Wed, 7 Feb 2018 18:30:17 +0900 Subject: wip --- src/web/app/auth/tags/form.tag | 2 +- src/web/app/auth/tags/index.tag | 2 +- src/web/app/ch/tags/channel.tag | 6 +- src/web/app/ch/tags/header.tag | 2 +- src/web/app/ch/tags/index.tag | 2 +- src/web/app/common/tags/activity-table.tag | 2 +- src/web/app/common/tags/authorized-apps.tag | 2 +- src/web/app/common/tags/ellipsis.tag | 2 +- src/web/app/common/tags/error.tag | 4 +- src/web/app/common/tags/file-type-icon.tag | 2 +- src/web/app/common/tags/forkit.tag | 2 +- src/web/app/common/tags/introduction.tag | 2 +- src/web/app/common/tags/messaging/form.tag | 2 +- src/web/app/common/tags/messaging/index.tag | 2 +- src/web/app/common/tags/messaging/message.tag | 2 +- src/web/app/common/tags/messaging/room.tag | 2 +- src/web/app/common/tags/nav-links.tag | 2 +- src/web/app/common/tags/number.tag | 2 +- src/web/app/common/tags/poll-editor.tag | 2 +- src/web/app/common/tags/poll.tag | 2 +- src/web/app/common/tags/post-menu.tag | 2 +- src/web/app/common/tags/raw.tag | 2 +- src/web/app/common/tags/reaction-icon.tag | 2 +- src/web/app/common/tags/reaction-picker.vue | 168 ++++++++++----------- src/web/app/common/tags/reactions-viewer.tag | 2 +- src/web/app/common/tags/signin-history.tag | 4 +- src/web/app/common/tags/signin.tag | 2 +- src/web/app/common/tags/signup.tag | 2 +- src/web/app/common/tags/special-message.tag | 2 +- src/web/app/common/tags/stream-indicator.vue | 2 +- src/web/app/common/tags/twitter-setting.tag | 2 +- src/web/app/common/tags/uploader.tag | 2 +- src/web/app/desktop/tags/analog-clock.tag | 2 +- .../app/desktop/tags/autocomplete-suggestion.tag | 2 +- src/web/app/desktop/tags/big-follow-button.tag | 2 +- src/web/app/desktop/tags/contextmenu.tag | 2 +- src/web/app/desktop/tags/crop-window.tag | 2 +- src/web/app/desktop/tags/detailed-post-window.tag | 2 +- src/web/app/desktop/tags/dialog.tag | 2 +- src/web/app/desktop/tags/donation.tag | 2 +- src/web/app/desktop/tags/drive/browser-window.tag | 2 +- src/web/app/desktop/tags/drive/browser.tag | 2 +- src/web/app/desktop/tags/drive/file.tag | 2 +- src/web/app/desktop/tags/drive/folder.tag | 2 +- src/web/app/desktop/tags/drive/nav-folder.tag | 2 +- src/web/app/desktop/tags/ellipsis-icon.tag | 2 +- src/web/app/desktop/tags/follow-button.tag | 2 +- src/web/app/desktop/tags/following-setuper.tag | 2 +- .../app/desktop/tags/home-widgets/access-log.tag | 2 +- src/web/app/desktop/tags/home-widgets/activity.tag | 2 +- .../app/desktop/tags/home-widgets/broadcast.tag | 2 +- src/web/app/desktop/tags/home-widgets/calendar.tag | 2 +- src/web/app/desktop/tags/home-widgets/channel.tag | 8 +- src/web/app/desktop/tags/home-widgets/donation.tag | 2 +- src/web/app/desktop/tags/home-widgets/mentions.tag | 2 +- .../app/desktop/tags/home-widgets/messaging.tag | 2 +- src/web/app/desktop/tags/home-widgets/nav.tag | 2 +- .../desktop/tags/home-widgets/notifications.tag | 2 +- .../app/desktop/tags/home-widgets/photo-stream.tag | 2 +- .../app/desktop/tags/home-widgets/post-form.tag | 2 +- src/web/app/desktop/tags/home-widgets/profile.tag | 2 +- .../tags/home-widgets/recommended-polls.tag | 2 +- .../app/desktop/tags/home-widgets/rss-reader.tag | 2 +- src/web/app/desktop/tags/home-widgets/server.tag | 16 +- .../app/desktop/tags/home-widgets/slideshow.tag | 2 +- src/web/app/desktop/tags/home-widgets/timeline.tag | 2 +- .../app/desktop/tags/home-widgets/timemachine.tag | 2 +- src/web/app/desktop/tags/home-widgets/tips.tag | 2 +- src/web/app/desktop/tags/home-widgets/trends.tag | 2 +- .../tags/home-widgets/user-recommendation.tag | 2 +- src/web/app/desktop/tags/home-widgets/version.tag | 2 +- src/web/app/desktop/tags/home.tag | 2 +- src/web/app/desktop/tags/images.tag | 6 +- src/web/app/desktop/tags/input-dialog.tag | 2 +- src/web/app/desktop/tags/list-user.tag | 2 +- src/web/app/desktop/tags/messaging/room-window.tag | 2 +- src/web/app/desktop/tags/messaging/window.tag | 2 +- src/web/app/desktop/tags/notifications.tag | 2 +- src/web/app/desktop/tags/pages/drive.tag | 2 +- src/web/app/desktop/tags/pages/entrance.tag | 6 +- src/web/app/desktop/tags/pages/home-customize.tag | 2 +- src/web/app/desktop/tags/pages/home.tag | 2 +- src/web/app/desktop/tags/pages/messaging-room.tag | 2 +- src/web/app/desktop/tags/pages/not-found.tag | 2 +- src/web/app/desktop/tags/pages/post.tag | 2 +- src/web/app/desktop/tags/pages/search.tag | 2 +- src/web/app/desktop/tags/pages/selectdrive.tag | 2 +- src/web/app/desktop/tags/pages/user.tag | 2 +- src/web/app/desktop/tags/post-detail-sub.tag | 2 +- src/web/app/desktop/tags/post-detail.tag | 2 +- src/web/app/desktop/tags/post-form-window.tag | 2 +- src/web/app/desktop/tags/post-form.tag | 2 +- src/web/app/desktop/tags/post-preview.tag | 2 +- src/web/app/desktop/tags/progress-dialog.tag | 2 +- src/web/app/desktop/tags/repost-form-window.tag | 2 +- src/web/app/desktop/tags/repost-form.tag | 2 +- src/web/app/desktop/tags/search-posts.tag | 2 +- src/web/app/desktop/tags/search.tag | 2 +- .../desktop/tags/select-file-from-drive-window.tag | 2 +- .../tags/select-folder-from-drive-window.tag | 2 +- src/web/app/desktop/tags/set-avatar-suggestion.tag | 2 +- src/web/app/desktop/tags/set-banner-suggestion.tag | 2 +- src/web/app/desktop/tags/settings-window.tag | 2 +- src/web/app/desktop/tags/settings.tag | 14 +- src/web/app/desktop/tags/sub-post-content.tag | 2 +- src/web/app/desktop/tags/timeline.tag | 6 +- src/web/app/desktop/tags/ui.tag | 18 +-- src/web/app/desktop/tags/user-followers-window.tag | 2 +- src/web/app/desktop/tags/user-followers.tag | 2 +- src/web/app/desktop/tags/user-following-window.tag | 2 +- src/web/app/desktop/tags/user-following.tag | 2 +- src/web/app/desktop/tags/user-preview.tag | 2 +- src/web/app/desktop/tags/user-timeline.tag | 2 +- src/web/app/desktop/tags/user.tag | 18 +-- src/web/app/desktop/tags/users-list.tag | 2 +- src/web/app/desktop/tags/widgets/activity.tag | 6 +- src/web/app/desktop/tags/widgets/calendar.tag | 2 +- src/web/app/desktop/tags/window.tag | 2 +- src/web/app/dev/tags/new-app-form.tag | 2 +- src/web/app/dev/tags/pages/app.tag | 2 +- src/web/app/dev/tags/pages/apps.tag | 2 +- src/web/app/dev/tags/pages/index.tag | 2 +- src/web/app/dev/tags/pages/new-app.tag | 2 +- src/web/app/mobile/tags/drive-folder-selector.tag | 2 +- src/web/app/mobile/tags/drive-selector.tag | 2 +- src/web/app/mobile/tags/drive.tag | 2 +- src/web/app/mobile/tags/drive/file-viewer.tag | 2 +- src/web/app/mobile/tags/drive/file.tag | 2 +- src/web/app/mobile/tags/drive/folder.tag | 2 +- src/web/app/mobile/tags/follow-button.tag | 2 +- src/web/app/mobile/tags/home-timeline.tag | 2 +- src/web/app/mobile/tags/home.tag | 2 +- src/web/app/mobile/tags/images.tag | 4 +- src/web/app/mobile/tags/init-following.tag | 2 +- src/web/app/mobile/tags/notification-preview.tag | 2 +- src/web/app/mobile/tags/notification.tag | 2 +- src/web/app/mobile/tags/notifications.tag | 2 +- src/web/app/mobile/tags/notify.tag | 2 +- src/web/app/mobile/tags/page/drive.tag | 2 +- src/web/app/mobile/tags/page/entrance.tag | 2 +- src/web/app/mobile/tags/page/entrance/signin.tag | 2 +- src/web/app/mobile/tags/page/entrance/signup.tag | 2 +- src/web/app/mobile/tags/page/home.tag | 2 +- src/web/app/mobile/tags/page/messaging-room.tag | 2 +- src/web/app/mobile/tags/page/messaging.tag | 2 +- src/web/app/mobile/tags/page/new-post.tag | 2 +- src/web/app/mobile/tags/page/notifications.tag | 2 +- src/web/app/mobile/tags/page/post.tag | 2 +- src/web/app/mobile/tags/page/search.tag | 2 +- src/web/app/mobile/tags/page/selectdrive.tag | 2 +- src/web/app/mobile/tags/page/settings.tag | 4 +- .../mobile/tags/page/settings/authorized-apps.tag | 2 +- src/web/app/mobile/tags/page/settings/profile.tag | 4 +- src/web/app/mobile/tags/page/settings/signin.tag | 2 +- src/web/app/mobile/tags/page/settings/twitter.tag | 2 +- src/web/app/mobile/tags/page/user-followers.tag | 2 +- src/web/app/mobile/tags/page/user-following.tag | 2 +- src/web/app/mobile/tags/page/user.tag | 2 +- src/web/app/mobile/tags/post-detail.tag | 4 +- src/web/app/mobile/tags/post-form.tag | 2 +- src/web/app/mobile/tags/post-preview.tag | 2 +- src/web/app/mobile/tags/search-posts.tag | 2 +- src/web/app/mobile/tags/search.tag | 2 +- src/web/app/mobile/tags/sub-post-content.tag | 2 +- src/web/app/mobile/tags/timeline.tag | 6 +- src/web/app/mobile/tags/ui.tag | 6 +- src/web/app/mobile/tags/user-card.tag | 2 +- src/web/app/mobile/tags/user-followers.tag | 2 +- src/web/app/mobile/tags/user-following.tag | 2 +- src/web/app/mobile/tags/user-preview.tag | 2 +- src/web/app/mobile/tags/user-timeline.tag | 2 +- src/web/app/mobile/tags/user.tag | 20 +-- src/web/app/mobile/tags/users-list.tag | 2 +- src/web/app/stats/tags/index.tag | 10 +- src/web/app/status/tags/index.tag | 8 +- 175 files changed, 324 insertions(+), 328 deletions(-) (limited to 'src/web/app/dev') diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag index 5bb27c269e..8f60aadb54 100644 --- a/src/web/app/auth/tags/form.tag +++ b/src/web/app/auth/tags/form.tag @@ -29,7 +29,7 @@ - diff --git a/src/web/app/common/tags/forkit.tag b/src/web/app/common/tags/forkit.tag index 55d5731081..6a8d06e564 100644 --- a/src/web/app/common/tags/forkit.tag +++ b/src/web/app/common/tags/forkit.tag @@ -4,7 +4,7 @@ - diff --git a/src/web/app/common/tags/number.tag b/src/web/app/common/tags/number.tag index 7afb8b3983..4b1081a87c 100644 --- a/src/web/app/common/tags/number.tag +++ b/src/web/app/common/tags/number.tag @@ -1,5 +1,5 @@ - diff --git a/src/web/app/common/tags/poll-editor.tag b/src/web/app/common/tags/poll-editor.tag index f660032c92..28e059e877 100644 --- a/src/web/app/common/tags/poll-editor.tag +++ b/src/web/app/common/tags/poll-editor.tag @@ -14,7 +14,7 @@ - diff --git a/src/web/app/common/tags/reaction-icon.tag b/src/web/app/common/tags/reaction-icon.tag index 0127293917..50d62cfba1 100644 --- a/src/web/app/common/tags/reaction-icon.tag +++ b/src/web/app/common/tags/reaction-icon.tag @@ -9,7 +9,7 @@ %i18n:common.reactions.confused% %i18n:common.reactions.pudding% - - - + position absolute + top -($balloon-size * 2) + left s('calc(50% - %s)', $balloon-size) + border-top solid $balloon-size transparent + border-left solid $balloon-size transparent + border-right solid $balloon-size transparent + border-bottom solid $balloon-size $border-color + + &:after + content "" + display block + position absolute + top -($balloon-size * 2) + 1.5px + left s('calc(50% - %s)', $balloon-size) + border-top solid $balloon-size transparent + border-left solid $balloon-size transparent + border-right solid $balloon-size transparent + border-bottom solid $balloon-size #fff + + > p + display block + margin 0 + padding 8px 10px + font-size 14px + color #586069 + border-bottom solid 1px #e1e4e8 + + > div + padding 4px + width 240px + text-align center + + > button + width 40px + height 40px + font-size 24px + border-radius 2px + + &:hover + background #eee + + &:active + background $theme-color + box-shadow inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15) + + diff --git a/src/web/app/common/tags/reactions-viewer.tag b/src/web/app/common/tags/reactions-viewer.tag index 50fb023f70..8ec14a12f8 100644 --- a/src/web/app/common/tags/reactions-viewer.tag +++ b/src/web/app/common/tags/reactions-viewer.tag @@ -10,7 +10,7 @@ { reactions.confused } { reactions.pudding } - diff --git a/src/web/app/desktop/tags/home-widgets/broadcast.tag b/src/web/app/desktop/tags/home-widgets/broadcast.tag index 157c429634..a1bd2175d8 100644 --- a/src/web/app/desktop/tags/home-widgets/broadcast.tag +++ b/src/web/app/desktop/tags/home-widgets/broadcast.tag @@ -14,7 +14,7 @@ }

%i18n:desktop.tags.mk-broadcast-home-widget.have-a-nice-day%

1 } @click="next">%i18n:desktop.tags.mk-broadcast-home-widget.next% >> - diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag index 9246d0e10c..2135a836c9 100644 --- a/src/web/app/desktop/tags/home-widgets/tips.tag +++ b/src/web/app/desktop/tags/home-widgets/tips.tag @@ -1,6 +1,6 @@

%fa:R lightbulb%

- - diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag index 62df62a484..206592518b 100644 --- a/src/web/app/desktop/tags/pages/home.tag +++ b/src/web/app/desktop/tags/pages/home.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/desktop/tags/pages/messaging-room.tag b/src/web/app/desktop/tags/pages/messaging-room.tag index 3c21b97501..48096ec803 100644 --- a/src/web/app/desktop/tags/pages/messaging-room.tag +++ b/src/web/app/desktop/tags/pages/messaging-room.tag @@ -1,7 +1,7 @@ - diff --git a/src/web/app/desktop/tags/pages/post.tag b/src/web/app/desktop/tags/pages/post.tag index 6d3b030e05..43f040ed20 100644 --- a/src/web/app/desktop/tags/pages/post.tag +++ b/src/web/app/desktop/tags/pages/post.tag @@ -6,7 +6,7 @@ %fa:angle-down%%i18n:desktop.tags.mk-post-page.prev% - diff --git a/src/web/app/desktop/tags/pages/selectdrive.tag b/src/web/app/desktop/tags/pages/selectdrive.tag index d497a47c00..723a1dd5aa 100644 --- a/src/web/app/desktop/tags/pages/selectdrive.tag +++ b/src/web/app/desktop/tags/pages/selectdrive.tag @@ -6,7 +6,7 @@ - diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag index 2d79ddd1e7..62f09d4e29 100644 --- a/src/web/app/desktop/tags/post-detail-sub.tag +++ b/src/web/app/desktop/tags/post-detail-sub.tag @@ -21,7 +21,7 @@ - @@ -56,7 +56,7 @@ - diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag index 43db70fcf2..fbacee1376 100644 --- a/src/web/app/dev/tags/pages/apps.tag +++ b/src/web/app/dev/tags/pages/apps.tag @@ -10,7 +10,7 @@ - diff --git a/src/web/app/dev/tags/pages/index.tag b/src/web/app/dev/tags/pages/index.tag index f863876fa7..ca270b3774 100644 --- a/src/web/app/dev/tags/pages/index.tag +++ b/src/web/app/dev/tags/pages/index.tag @@ -1,5 +1,5 @@ アプリ - diff --git a/src/web/app/dev/tags/pages/new-app.tag b/src/web/app/dev/tags/pages/new-app.tag index 238b6865e1..26185f278b 100644 --- a/src/web/app/dev/tags/pages/new-app.tag +++ b/src/web/app/dev/tags/pages/new-app.tag @@ -6,7 +6,7 @@ - diff --git a/src/web/app/mobile/tags/page/entrance.tag b/src/web/app/mobile/tags/page/entrance.tag index b5da3c947b..ebcf30f80a 100644 --- a/src/web/app/mobile/tags/page/entrance.tag +++ b/src/web/app/mobile/tags/page/entrance.tag @@ -10,7 +10,7 @@

{ _COPYRIGHT_ }

- diff --git a/src/web/app/mobile/tags/page/messaging-room.tag b/src/web/app/mobile/tags/page/messaging-room.tag index 00ee265120..075ea8e83e 100644 --- a/src/web/app/mobile/tags/page/messaging-room.tag +++ b/src/web/app/mobile/tags/page/messaging-room.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/messaging.tag b/src/web/app/mobile/tags/page/messaging.tag index 76d6103777..acde6f2693 100644 --- a/src/web/app/mobile/tags/page/messaging.tag +++ b/src/web/app/mobile/tags/page/messaging.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/new-post.tag b/src/web/app/mobile/tags/page/new-post.tag index 7adde3b329..1650446b43 100644 --- a/src/web/app/mobile/tags/page/new-post.tag +++ b/src/web/app/mobile/tags/page/new-post.tag @@ -1,6 +1,6 @@ - diff --git a/src/web/app/mobile/tags/page/notifications.tag b/src/web/app/mobile/tags/page/notifications.tag index 596467d476..97717e2e2a 100644 --- a/src/web/app/mobile/tags/page/notifications.tag +++ b/src/web/app/mobile/tags/page/notifications.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/post.tag b/src/web/app/mobile/tags/page/post.tag index 5303ca8d34..003f9dea56 100644 --- a/src/web/app/mobile/tags/page/post.tag +++ b/src/web/app/mobile/tags/page/post.tag @@ -8,7 +8,7 @@ %fa:angle-down%%i18n:mobile.tags.mk-post-page.prev% - diff --git a/src/web/app/mobile/tags/page/selectdrive.tag b/src/web/app/mobile/tags/page/selectdrive.tag index 172a161ec3..c7ff66d050 100644 --- a/src/web/app/mobile/tags/page/selectdrive.tag +++ b/src/web/app/mobile/tags/page/selectdrive.tag @@ -6,7 +6,7 @@ - @@ -29,7 +29,7 @@
  • %fa:power-off%%i18n:mobile.tags.mk-settings-page.signout%
  • ver { _VERSION_ } (葵 aoi)

    - diff --git a/src/web/app/mobile/tags/page/settings/profile.tag b/src/web/app/mobile/tags/page/settings/profile.tag index 5d6c477940..e213f40706 100644 --- a/src/web/app/mobile/tags/page/settings/profile.tag +++ b/src/web/app/mobile/tags/page/settings/profile.tag @@ -2,7 +2,7 @@ - @@ -51,7 +51,7 @@ - diff --git a/src/web/app/mobile/tags/page/settings/twitter.tag b/src/web/app/mobile/tags/page/settings/twitter.tag index 02661d3b6b..672eff25be 100644 --- a/src/web/app/mobile/tags/page/settings/twitter.tag +++ b/src/web/app/mobile/tags/page/settings/twitter.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/user-followers.tag b/src/web/app/mobile/tags/page/user-followers.tag index a5e63613c6..50280e7b99 100644 --- a/src/web/app/mobile/tags/page/user-followers.tag +++ b/src/web/app/mobile/tags/page/user-followers.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/user-following.tag b/src/web/app/mobile/tags/page/user-following.tag index b4ed107834..b28efbab94 100644 --- a/src/web/app/mobile/tags/page/user-following.tag +++ b/src/web/app/mobile/tags/page/user-following.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/page/user.tag b/src/web/app/mobile/tags/page/user.tag index 8eec733fcd..04b7276364 100644 --- a/src/web/app/mobile/tags/page/user.tag +++ b/src/web/app/mobile/tags/page/user.tag @@ -2,7 +2,7 @@ - diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag index be377d77f5..e397ce7c0b 100644 --- a/src/web/app/mobile/tags/post-detail.tag +++ b/src/web/app/mobile/tags/post-detail.tag @@ -62,7 +62,7 @@ - diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag index 7192cd0130..3d9175b18c 100644 --- a/src/web/app/mobile/tags/sub-post-content.tag +++ b/src/web/app/mobile/tags/sub-post-content.tag @@ -8,7 +8,7 @@ %i18n:mobile.tags.mk-sub-post-content.poll% - @@ -85,7 +85,7 @@

    %i18n:stats.users-count% { stats.users_count }

    - @@ -133,7 +133,7 @@ stroke="#555" stroke-dasharray="2 2"/> - @@ -107,7 +107,7 @@

    MEM { percentage }%

    - @@ -164,7 +164,7 @@ stroke="#f43b16" stroke-width="0.5"/> - - - diff --git a/src/web/app/common/tags/reactions-viewer.vue b/src/web/app/common/tags/reactions-viewer.vue new file mode 100644 index 0000000000..ad126ff1d5 --- /dev/null +++ b/src/web/app/common/tags/reactions-viewer.vue @@ -0,0 +1,55 @@ + + + + + + + + + + diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag index 332bfdccfa..e6b57c091f 100644 --- a/src/web/app/common/tags/signin-history.tag +++ b/src/web/app/common/tags/signin-history.tag @@ -1,5 +1,5 @@ -
    +
    - diff --git a/src/web/app/ch/tags/index.tag b/src/web/app/ch/tags/index.tag index e058da6a3f..6e0b451e8a 100644 --- a/src/web/app/ch/tags/index.tag +++ b/src/web/app/ch/tags/index.tag @@ -11,7 +11,7 @@ display block - diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag index df0658741f..e9d2c01caa 100644 --- a/src/web/app/common/tags/messaging/form.tag +++ b/src/web/app/common/tags/messaging/form.tag @@ -116,7 +116,7 @@ display none - diff --git a/src/web/app/common/tags/number.tag b/src/web/app/common/tags/number.tag index 4b1081a87c..9cbbacd2c7 100644 --- a/src/web/app/common/tags/number.tag +++ b/src/web/app/common/tags/number.tag @@ -3,7 +3,7 @@ :scope display inline - diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag index d4569216c6..2ca1fa502d 100644 --- a/src/web/app/desktop/tags/home-widgets/mentions.tag +++ b/src/web/app/desktop/tags/home-widgets/mentions.tag @@ -52,7 +52,7 @@ color #ccc - diff --git a/src/web/app/desktop/tags/home-widgets/notifications.tag b/src/web/app/desktop/tags/home-widgets/notifications.tag index 4a6d7b4170..4c48da6592 100644 --- a/src/web/app/desktop/tags/home-widgets/notifications.tag +++ b/src/web/app/desktop/tags/home-widgets/notifications.tag @@ -46,7 +46,7 @@ overflow auto - @@ -516,7 +516,7 @@ fill rgba(0, 0, 0, 0.6) - diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag index f727c3e808..827622930d 100644 --- a/src/web/app/desktop/tags/home.tag +++ b/src/web/app/desktop/tags/home.tag @@ -180,7 +180,7 @@ margin 0 auto - + diff --git a/src/web/app/desktop/tags/messaging/room-window.tag b/src/web/app/desktop/tags/messaging/room-window.tag index b13c2d3e90..ca11873644 100644 --- a/src/web/app/desktop/tags/messaging/room-window.tag +++ b/src/web/app/desktop/tags/messaging/room-window.tag @@ -18,7 +18,7 @@ overflow auto - + @@ -175,7 +175,7 @@ box-shadow 0 0 0 2px rgba($theme-color, 0.5) !important - + diff --git a/src/web/app/desktop/tags/user-followers.tag b/src/web/app/desktop/tags/user-followers.tag index 79fa871413..a1b44f0f5b 100644 --- a/src/web/app/desktop/tags/user-followers.tag +++ b/src/web/app/desktop/tags/user-followers.tag @@ -6,7 +6,7 @@ height 100% - + diff --git a/src/web/app/desktop/tags/user-following.tag b/src/web/app/desktop/tags/user-following.tag index 260900f951..db46bf110e 100644 --- a/src/web/app/desktop/tags/user-following.tag +++ b/src/web/app/desktop/tags/user-following.tag @@ -6,7 +6,7 @@ height 100% - + diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag index 01c0748fea..1c0282e771 100644 --- a/src/web/app/mobile/tags/post-form.tag +++ b/src/web/app/mobile/tags/post-form.tag @@ -144,7 +144,7 @@ box-shadow none - + diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag index 9cb5ee36f4..00936a8385 100644 --- a/src/web/app/mobile/tags/search-posts.tag +++ b/src/web/app/mobile/tags/search-posts.tag @@ -14,7 +14,7 @@ margin 16px auto width calc(100% - 32px) - + diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index 0c783b8f3a..16fb116eb6 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -10,7 +10,7 @@ display block padding-top 48px - diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag index a4dc99e68a..02368045e0 100644 --- a/src/web/app/mobile/tags/user-followers.tag +++ b/src/web/app/mobile/tags/user-followers.tag @@ -5,7 +5,7 @@ display block - + diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag index dd878810cf..270a3744c3 100644 --- a/src/web/app/mobile/tags/user-timeline.tag +++ b/src/web/app/mobile/tags/user-timeline.tag @@ -6,7 +6,7 @@ max-width 600px margin 0 auto - @@ -620,7 +620,7 @@ margin-right 4px - @@ -658,7 +658,7 @@ margin-right 4px - diff --git a/src/web/app/mobile/tags/page/post.tag b/src/web/app/mobile/tags/page/post.tag index 5e8cd24481..ed7cb52546 100644 --- a/src/web/app/mobile/tags/page/post.tag +++ b/src/web/app/mobile/tags/page/post.tag @@ -60,7 +60,7 @@ Progress.start(); - this.api('posts/show', { + this.$root.$data.os.api('posts/show', { post_id: this.opts.post }).then(post => { diff --git a/src/web/app/mobile/tags/page/settings/profile.tag b/src/web/app/mobile/tags/page/settings/profile.tag index cafe65f274..6f7ef3ac30 100644 --- a/src/web/app/mobile/tags/page/settings/profile.tag +++ b/src/web/app/mobile/tags/page/settings/profile.tag @@ -182,7 +182,7 @@ avatarSaving: true }); - this.api('i/update', { + this.$root.$data.os.api('i/update', { avatar_id: file.id }).then(() => { this.update({ @@ -203,7 +203,7 @@ bannerSaving: true }); - this.api('i/update', { + this.$root.$data.os.api('i/update', { banner_id: file.id }).then(() => { this.update({ @@ -230,7 +230,7 @@ saving: true }); - this.api('i/update', { + this.$root.$data.os.api('i/update', { name: this.$refs.name.value, location: this.$refs.location.value || null, description: this.$refs.description.value || null, diff --git a/src/web/app/mobile/tags/page/user-followers.tag b/src/web/app/mobile/tags/page/user-followers.tag index 1123fd4224..a658094841 100644 --- a/src/web/app/mobile/tags/page/user-followers.tag +++ b/src/web/app/mobile/tags/page/user-followers.tag @@ -18,7 +18,7 @@ this.on('mount', () => { Progress.start(); - this.api('users/show', { + this.$root.$data.os.api('users/show', { username: this.opts.user }).then(user => { this.update({ diff --git a/src/web/app/mobile/tags/page/user-following.tag b/src/web/app/mobile/tags/page/user-following.tag index b1c22cae1e..8fe0f5fcee 100644 --- a/src/web/app/mobile/tags/page/user-following.tag +++ b/src/web/app/mobile/tags/page/user-following.tag @@ -18,7 +18,7 @@ this.on('mount', () => { Progress.start(); - this.api('users/show', { + this.$root.$data.os.api('users/show', { username: this.opts.user }).then(user => { this.update({ diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag index d812aba42a..4b8566f962 100644 --- a/src/web/app/mobile/tags/post-detail.tag +++ b/src/web/app/mobile/tags/post-detail.tag @@ -291,7 +291,7 @@ // Get replies if (!this.compact) { - this.api('posts/replies', { + this.$root.$data.os.api('posts/replies', { post_id: this.p.id, limit: 8 }).then(replies => { @@ -311,7 +311,7 @@ this.repost = () => { const text = window.prompt(`「${this.summary}」をRepost`); if (text == null) return; - this.api('posts/create', { + this.$root.$data.os.api('posts/create', { repost_id: this.p.id, text: text == '' ? undefined : text }); @@ -337,7 +337,7 @@ this.contextFetching = true; // Fetch context - this.api('posts/context', { + this.$root.$data.os.api('posts/context', { post_id: this.p.reply_id }).then(context => { this.update({ diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag index c650fbce5c..7b4d73f2d6 100644 --- a/src/web/app/mobile/tags/search-posts.tag +++ b/src/web/app/mobile/tags/search-posts.tag @@ -25,7 +25,7 @@ this.query = this.opts.query; this.init = new Promise((res, rej) => { - this.api('posts/search', parse(this.query)).then(posts => { + this.$root.$data.os.api('posts/search', parse(this.query)).then(posts => { res(posts); this.$emit('loaded'); }); @@ -33,7 +33,7 @@ this.more = () => { this.offset += this.limit; - return this.api('posts/search', Object.assign({}, parse(this.query), { + return this.$root.$data.os.api('posts/search', Object.assign({}, parse(this.query), { limit: this.limit, offset: this.offset })); diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag index b9101e2121..f3f70b2a67 100644 --- a/src/web/app/mobile/tags/user-followers.tag +++ b/src/web/app/mobile/tags/user-followers.tag @@ -11,7 +11,7 @@ this.user = this.opts.user; this.fetch = (iknow, limit, cursor, cb) => { - this.api('users/followers', { + this.$root.$data.os.api('users/followers', { user_id: this.user.id, iknow: iknow, limit: limit, diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag index 5cfe60fec5..b767571432 100644 --- a/src/web/app/mobile/tags/user-following.tag +++ b/src/web/app/mobile/tags/user-following.tag @@ -11,7 +11,7 @@ this.user = this.opts.user; this.fetch = (iknow, limit, cursor, cb) => { - this.api('users/following', { + this.$root.$data.os.api('users/following', { user_id: this.user.id, iknow: iknow, limit: limit, diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag index b9f5dfbd5d..546558155a 100644 --- a/src/web/app/mobile/tags/user-timeline.tag +++ b/src/web/app/mobile/tags/user-timeline.tag @@ -13,7 +13,7 @@ this.withMedia = this.opts.withMedia; this.init = new Promise((res, rej) => { - this.api('users/posts', { + this.$root.$data.os.api('users/posts', { user_id: this.user.id, with_media: this.withMedia }).then(posts => { @@ -23,7 +23,7 @@ }); this.more = () => { - return this.api('users/posts', { + return this.$root.$data.os.api('users/posts', { user_id: this.user.id, with_media: this.withMedia, until_id: this.$refs.timeline.tail().id diff --git a/src/web/app/mobile/tags/user.tag b/src/web/app/mobile/tags/user.tag index 87e63471e8..b9bb4e17a4 100644 --- a/src/web/app/mobile/tags/user.tag +++ b/src/web/app/mobile/tags/user.tag @@ -196,7 +196,7 @@ this.fetching = true; this.on('mount', () => { - this.api('users/show', { + this.$root.$data.os.api('users/show', { username: this.username }).then(user => { this.fetching = false; @@ -348,7 +348,7 @@ this.initializing = true; this.on('mount', () => { - this.api('users/posts', { + this.$root.$data.os.api('users/posts', { user_id: this.user.id }).then(posts => { this.update({ @@ -485,7 +485,7 @@ this.user = this.opts.user; this.on('mount', () => { - this.api('users/posts', { + this.$root.$data.os.api('users/posts', { user_id: this.user.id, with_media: true, limit: 6 @@ -540,7 +540,7 @@ this.user = this.opts.user; this.on('mount', () => { - this.api('aggregation/users/activity', { + this.$root.$data.os.api('aggregation/users/activity', { user_id: this.user.id, limit: 30 }).then(data => { @@ -665,7 +665,7 @@ this.initializing = true; this.on('mount', () => { - this.api('users/get_frequently_replied_users', { + this.$root.$data.os.api('users/get_frequently_replied_users', { user_id: this.user.id }).then(x => { this.update({ @@ -720,7 +720,7 @@ this.initializing = true; this.on('mount', () => { - this.api('users/followers', { + this.$root.$data.os.api('users/followers', { user_id: this.user.id, iknow: true, limit: 30 diff --git a/src/web/app/mobile/views/components/follow-button.vue b/src/web/app/mobile/views/components/follow-button.vue index 455be388c1..047005cc9e 100644 --- a/src/web/app/mobile/views/components/follow-button.vue +++ b/src/web/app/mobile/views/components/follow-button.vue @@ -56,7 +56,7 @@ export default Vue.extend({ onClick() { this.wait = true; if (this.user.is_following) { - this.api('following/delete', { + this.$root.$data.os.api('following/delete', { user_id: this.user.id }).then(() => { this.user.is_following = false; @@ -66,7 +66,7 @@ export default Vue.extend({ this.wait = false; }); } else { - this.api('following/create', { + this.$root.$data.os.api('following/create', { user_id: this.user.id }).then(() => { this.user.is_following = true; diff --git a/src/web/app/stats/tags/index.tag b/src/web/app/stats/tags/index.tag index 3b2b10b0ae..4b167ccbc8 100644 --- a/src/web/app/stats/tags/index.tag +++ b/src/web/app/stats/tags/index.tag @@ -46,7 +46,7 @@ this.initializing = true; this.on('mount', () => { - this.api('stats').then(stats => { + this.$root.$data.os.api('stats').then(stats => { this.update({ initializing: false, stats @@ -70,7 +70,7 @@ this.stats = this.opts.stats; this.on('mount', () => { - this.api('aggregation/posts', { + this.$root.$data.os.api('aggregation/posts', { limit: 365 }).then(data => { this.update({ @@ -96,7 +96,7 @@ this.stats = this.opts.stats; this.on('mount', () => { - this.api('aggregation/users', { + this.$root.$data.os.api('aggregation/users', { limit: 365 }).then(data => { this.update({ diff --git a/src/web/app/status/tags/index.tag b/src/web/app/status/tags/index.tag index e06258c49e..899467097a 100644 --- a/src/web/app/status/tags/index.tag +++ b/src/web/app/status/tags/index.tag @@ -59,7 +59,7 @@ this.connection = new Connection(); this.on('mount', () => { - this.api('meta').then(meta => { + this.$root.$data.os.api('meta').then(meta => { this.update({ initializing: false, meta -- cgit v1.2.3-freya From 75c86a8f7fb5ad2b04dc410b04c928c9f9d94c0c Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 23 Feb 2018 02:53:36 +0900 Subject: :v: --- src/web/app/ch/router.ts | 32 -------------------------------- src/web/app/ch/script.ts | 3 --- src/web/app/dev/router.ts | 42 ------------------------------------------ src/web/app/dev/script.ts | 3 --- 4 files changed, 80 deletions(-) delete mode 100644 src/web/app/ch/router.ts delete mode 100644 src/web/app/dev/router.ts (limited to 'src/web/app/dev') diff --git a/src/web/app/ch/router.ts b/src/web/app/ch/router.ts deleted file mode 100644 index f10c4acdf0..0000000000 --- a/src/web/app/ch/router.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as riot from 'riot'; -import * as route from 'page'; -let page = null; - -export default () => { - route('/', index); - route('/:channel', channel); - route('*', notFound); - - function index() { - mount(document.createElement('mk-index')); - } - - function channel(ctx) { - const el = document.createElement('mk-channel'); - el.setAttribute('id', ctx.params.channel); - mount(el); - } - - function notFound() { - mount(document.createElement('mk-not-found')); - } - - // EXEC - (route as any)(); -}; - -function mount(content) { - if (page) page.unmount(); - const body = document.getElementById('app'); - page = riot.mount(body.appendChild(content))[0]; -} diff --git a/src/web/app/ch/script.ts b/src/web/app/ch/script.ts index e23558037c..4c6b6dfd1b 100644 --- a/src/web/app/ch/script.ts +++ b/src/web/app/ch/script.ts @@ -7,12 +7,9 @@ import './style.styl'; require('./tags'); import init from '../init'; -import route from './router'; /** * init */ init(() => { - // Start routing - route(); }); diff --git a/src/web/app/dev/router.ts b/src/web/app/dev/router.ts deleted file mode 100644 index fcd2b1f76b..0000000000 --- a/src/web/app/dev/router.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as riot from 'riot'; -import * as route from 'page'; -let page = null; - -export default () => { - route('/', index); - route('/apps', apps); - route('/app/new', newApp); - route('/app/:app', app); - route('*', notFound); - - function index() { - mount(document.createElement('mk-index')); - } - - function apps() { - mount(document.createElement('mk-apps-page')); - } - - function newApp() { - mount(document.createElement('mk-new-app-page')); - } - - function app(ctx) { - const el = document.createElement('mk-app-page'); - el.setAttribute('app', ctx.params.app); - mount(el); - } - - function notFound() { - mount(document.createElement('mk-not-found')); - } - - // EXEC - (route as any)(); -}; - -function mount(content) { - if (page) page.unmount(); - const body = document.getElementById('app'); - page = riot.mount(body.appendChild(content))[0]; -} diff --git a/src/web/app/dev/script.ts b/src/web/app/dev/script.ts index b115c5be48..bb43411195 100644 --- a/src/web/app/dev/script.ts +++ b/src/web/app/dev/script.ts @@ -7,12 +7,9 @@ import './style.styl'; require('./tags'); import init from '../init'; -import route from './router'; /** * init */ init(() => { - // Start routing - route(); }); -- cgit v1.2.3-freya From dbc421cb571f69a4c71691c00b094925006b95fe Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 28 Feb 2018 00:11:28 +0900 Subject: :v: --- src/web/app/auth/script.ts | 25 ++++ src/web/app/auth/views/index.vue | 8 +- src/web/app/dev/script.ts | 18 ++- src/web/app/dev/tags/index.ts | 5 - src/web/app/dev/tags/new-app-form.tag | 252 --------------------------------- src/web/app/dev/tags/pages/app.tag | 32 ----- src/web/app/dev/tags/pages/apps.tag | 33 ----- src/web/app/dev/tags/pages/index.tag | 6 - src/web/app/dev/tags/pages/new-app.tag | 42 ------ src/web/app/dev/views/app.vue | 43 ++++++ src/web/app/dev/views/apps.vue | 24 ++++ src/web/app/dev/views/index.vue | 10 ++ src/web/app/dev/views/new-app.vue | 145 +++++++++++++++++++ src/web/app/init.ts | 2 +- webpack/webpack.config.ts | 4 +- 15 files changed, 272 insertions(+), 377 deletions(-) create mode 100644 src/web/app/auth/script.ts delete mode 100644 src/web/app/dev/tags/index.ts delete mode 100644 src/web/app/dev/tags/new-app-form.tag delete mode 100644 src/web/app/dev/tags/pages/app.tag delete mode 100644 src/web/app/dev/tags/pages/apps.tag delete mode 100644 src/web/app/dev/tags/pages/index.tag delete mode 100644 src/web/app/dev/tags/pages/new-app.tag create mode 100644 src/web/app/dev/views/app.vue create mode 100644 src/web/app/dev/views/apps.vue create mode 100644 src/web/app/dev/views/index.vue create mode 100644 src/web/app/dev/views/new-app.vue (limited to 'src/web/app/dev') diff --git a/src/web/app/auth/script.ts b/src/web/app/auth/script.ts new file mode 100644 index 0000000000..31c758ebc2 --- /dev/null +++ b/src/web/app/auth/script.ts @@ -0,0 +1,25 @@ +/** + * Authorize Form + */ + +// Style +import './style.styl'; + +import init from '../init'; + +import Index from './views/index.vue'; + +/** + * init + */ +init(async (launch) => { + document.title = 'Misskey | アプリの連携'; + + // Launch the app + const [app] = launch(); + + // Routing + app.$router.addRoutes([ + { path: '/:token', component: Index }, + ]); +}); diff --git a/src/web/app/auth/views/index.vue b/src/web/app/auth/views/index.vue index 1e372c0bde..17e5cc6108 100644 --- a/src/web/app/auth/views/index.vue +++ b/src/web/app/auth/views/index.vue @@ -42,10 +42,14 @@ export default Vue.extend({ return { state: null, session: null, - fetching: true, - token: window.location.href.split('/').pop() + fetching: true }; }, + computed: { + token(): string { + return this.$route.params.token; + } + }, mounted() { if (!this.$root.$data.os.isSignedIn) return; diff --git a/src/web/app/dev/script.ts b/src/web/app/dev/script.ts index bb43411195..757bfca490 100644 --- a/src/web/app/dev/script.ts +++ b/src/web/app/dev/script.ts @@ -5,11 +5,25 @@ // Style import './style.styl'; -require('./tags'); import init from '../init'; +import Index from './views/index.vue'; +import Apps from './views/apps.vue'; +import AppNew from './views/new-app.vue'; +import App from './views/app.vue'; + /** * init */ -init(() => { +init(launch => { + // Launch the app + const [app] = launch(); + + // Routing + app.$router.addRoutes([ + { path: '/', component: Index }, + { path: '/app', component: Apps }, + { path: '/app/new', component: AppNew }, + { path: '/app/:id', component: App }, + ]); }); diff --git a/src/web/app/dev/tags/index.ts b/src/web/app/dev/tags/index.ts deleted file mode 100644 index 1e0c73697e..0000000000 --- a/src/web/app/dev/tags/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -require('./pages/index.tag'); -require('./pages/apps.tag'); -require('./pages/app.tag'); -require('./pages/new-app.tag'); -require('./new-app-form.tag'); diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag deleted file mode 100644 index cf3c440079..0000000000 --- a/src/web/app/dev/tags/new-app-form.tag +++ /dev/null @@ -1,252 +0,0 @@ - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -

    権限

    -
    - - - - - - - - - -
    -

    %fa:exclamation-triangle%アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。

    -
    - -
    - - -
    diff --git a/src/web/app/dev/tags/pages/app.tag b/src/web/app/dev/tags/pages/app.tag deleted file mode 100644 index 982549ed2b..0000000000 --- a/src/web/app/dev/tags/pages/app.tag +++ /dev/null @@ -1,32 +0,0 @@ - -

    読み込み中

    -
    -
    -

    { app.name }

    -
    -
    -

    App Secret

    - -
    -
    - - -
    diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag deleted file mode 100644 index 6ae6031e64..0000000000 --- a/src/web/app/dev/tags/pages/apps.tag +++ /dev/null @@ -1,33 +0,0 @@ - -

    アプリを管理

    アプリ作成 -
    -

    読み込み中

    - -
    - - -
    diff --git a/src/web/app/dev/tags/pages/index.tag b/src/web/app/dev/tags/pages/index.tag deleted file mode 100644 index ca270b3774..0000000000 --- a/src/web/app/dev/tags/pages/index.tag +++ /dev/null @@ -1,6 +0,0 @@ -アプリ - - diff --git a/src/web/app/dev/tags/pages/new-app.tag b/src/web/app/dev/tags/pages/new-app.tag deleted file mode 100644 index 26185f278b..0000000000 --- a/src/web/app/dev/tags/pages/new-app.tag +++ /dev/null @@ -1,42 +0,0 @@ - -
    -
    -

    新しいアプリを作成

    -

    MisskeyのAPIを利用したアプリケーションを作成できます。

    -
    - -
    - -
    diff --git a/src/web/app/dev/views/app.vue b/src/web/app/dev/views/app.vue new file mode 100644 index 0000000000..9eddabbec2 --- /dev/null +++ b/src/web/app/dev/views/app.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/web/app/dev/views/apps.vue b/src/web/app/dev/views/apps.vue new file mode 100644 index 0000000000..e8adbea2da --- /dev/null +++ b/src/web/app/dev/views/apps.vue @@ -0,0 +1,24 @@ + + + diff --git a/src/web/app/dev/views/index.vue b/src/web/app/dev/views/index.vue new file mode 100644 index 0000000000..a8429a56dd --- /dev/null +++ b/src/web/app/dev/views/index.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue new file mode 100644 index 0000000000..f2e5659a4e --- /dev/null +++ b/src/web/app/dev/views/new-app.vue @@ -0,0 +1,145 @@ + + + diff --git a/src/web/app/init.ts b/src/web/app/init.ts index 5c0b4c2d39..2e90d62d79 100644 --- a/src/web/app/init.ts +++ b/src/web/app/init.ts @@ -77,7 +77,7 @@ if (localStorage.getItem('should-refresh') == 'true') { } // MiOSを初期化してコールバックする -export default (callback: (launch: (api: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => { +export default (callback: (launch: (api?: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => { const os = new MiOS(sw); os.init(() => { diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts index 69e05dc8c6..775ecbd348 100644 --- a/webpack/webpack.config.ts +++ b/webpack/webpack.config.ts @@ -38,8 +38,8 @@ module.exports = Object.keys(langs).map(lang => { //ch: './src/web/app/ch/script.ts', //stats: './src/web/app/stats/script.ts', //status: './src/web/app/status/script.ts', - //dev: './src/web/app/dev/script.ts', - //auth: './src/web/app/auth/script.ts', + dev: './src/web/app/dev/script.ts', + auth: './src/web/app/auth/script.ts', sw: './src/web/app/sw.js' }; -- cgit v1.2.3-freya From 41635ca3d34c8538ce78be8cc11f0f592fda1b62 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 28 Feb 2018 00:30:36 +0900 Subject: oops --- src/web/app/dev/views/apps.vue | 15 ++++++++++++++- src/web/app/init.ts | 4 ++-- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'src/web/app/dev') diff --git a/src/web/app/dev/views/apps.vue b/src/web/app/dev/views/apps.vue index e8adbea2da..42b4abc9b8 100644 --- a/src/web/app/dev/views/apps.vue +++ b/src/web/app/dev/views/apps.vue @@ -20,5 +20,18 @@ diff --git a/src/web/app/init.ts b/src/web/app/init.ts index 2e90d62d79..f9855fd5c9 100644 --- a/src/web/app/init.ts +++ b/src/web/app/init.ts @@ -84,8 +84,8 @@ export default (callback: (launch: (api?: (os: MiOS) => API) => [Vue, MiOS]) => // アプリ基底要素マウント document.body.innerHTML = '
    '; - const launch = (api: (os: MiOS) => API) => { - os.apis = api(os); + const launch = (api?: (os: MiOS) => API) => { + os.apis = api ? api(os) : null; Vue.mixin({ data() { -- cgit v1.2.3-freya From dd232b996a8cd4cb9be9ce0c3b81d6045013bb36 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 28 Feb 2018 05:43:14 +0900 Subject: :v: --- package.json | 1 + src/web/app/dev/script.ts | 12 +++- src/web/app/dev/style.styl | 5 ++ src/web/app/dev/views/app.vue | 18 +++--- src/web/app/dev/views/apps.vue | 34 +++++------ src/web/app/dev/views/index.vue | 6 +- src/web/app/dev/views/new-app.vue | 118 +++++++++++++------------------------- src/web/app/dev/views/ui.vue | 20 +++++++ 8 files changed, 103 insertions(+), 111 deletions(-) create mode 100644 src/web/app/dev/views/ui.vue (limited to 'src/web/app/dev') diff --git a/package.json b/package.json index 689fd2cc65..0f651147bb 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "autwh": "0.0.1", "bcryptjs": "2.4.3", "body-parser": "1.18.2", + "bootstrap-vue": "^2.0.0-rc.1", "cache-loader": "1.2.0", "cafy": "3.2.1", "chai": "4.1.2", diff --git a/src/web/app/dev/script.ts b/src/web/app/dev/script.ts index 757bfca490..2f4a16fab1 100644 --- a/src/web/app/dev/script.ts +++ b/src/web/app/dev/script.ts @@ -2,6 +2,11 @@ * Developer Center */ +import Vue from 'vue'; +import BootstrapVue from 'bootstrap-vue'; +import 'bootstrap/dist/css/bootstrap.css'; +import 'bootstrap-vue/dist/bootstrap-vue.css'; + // Style import './style.styl'; @@ -11,6 +16,11 @@ import Index from './views/index.vue'; import Apps from './views/apps.vue'; import AppNew from './views/new-app.vue'; import App from './views/app.vue'; +import ui from './views/ui.vue'; + +Vue.use(BootstrapVue); + +Vue.component('mk-ui', ui); /** * init @@ -22,7 +32,7 @@ init(launch => { // Routing app.$router.addRoutes([ { path: '/', component: Index }, - { path: '/app', component: Apps }, + { path: '/apps', component: Apps }, { path: '/app/new', component: AppNew }, { path: '/app/:id', component: App }, ]); diff --git a/src/web/app/dev/style.styl b/src/web/app/dev/style.styl index cdbcb0e261..e635897b17 100644 --- a/src/web/app/dev/style.styl +++ b/src/web/app/dev/style.styl @@ -1,5 +1,10 @@ @import "../app" @import "../reset" +// Bootstrapのデザインを崩すので: +* + position initial + background-clip initial !important + html background-color #fff diff --git a/src/web/app/dev/views/app.vue b/src/web/app/dev/views/app.vue index 9eddabbec2..2c2a3c83ce 100644 --- a/src/web/app/dev/views/app.vue +++ b/src/web/app/dev/views/app.vue @@ -1,16 +1,12 @@ + + diff --git a/src/server/web/app/auth/views/index.vue b/src/server/web/app/auth/views/index.vue new file mode 100644 index 0000000000..17e5cc6108 --- /dev/null +++ b/src/server/web/app/auth/views/index.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/src/server/web/app/base.pug b/src/server/web/app/base.pug new file mode 100644 index 0000000000..60eb1539ec --- /dev/null +++ b/src/server/web/app/base.pug @@ -0,0 +1,38 @@ +doctype html + +!= '\n\n' + +html + + head + meta(charset='utf-8') + meta(name='application-name' content='Misskey') + meta(name='theme-color' content=themeColor) + meta(name='referrer' content='origin') + link(rel='manifest' href='/manifest.json') + + title Misskey + + style + include ./../../../../built/server/web/assets/init.css + script + include ./../../../../built/server/web/assets/boot.js + + script + include ./../../../../built/server/web/assets/safe.js + + //- FontAwesome style + style #{facss} + + //- highlight.js style + style #{hljscss} + + body + noscript: p + | JavaScriptを有効にしてください + br + | Please turn on your JavaScript + div#ini: p + span . + span . + span . diff --git a/src/server/web/app/boot.js b/src/server/web/app/boot.js new file mode 100644 index 0000000000..0846e4bd55 --- /dev/null +++ b/src/server/web/app/boot.js @@ -0,0 +1,120 @@ +/** + * MISSKEY BOOT LOADER + * (ENTRY POINT) + */ + +/** + * ドメインに基づいて適切なスクリプトを読み込みます。 + * ユーザーの言語およびモバイル端末か否かも考慮します。 + * webpackは介さないためrequireやimportは使えません。 + */ + +'use strict'; + +// Chromeで確認したことなのですが、constやletを用いたとしても +// グローバルなスコープで定数/変数を定義するとwindowのプロパティ +// としてそれがアクセスできるようになる訳ではありませんが、普通に +// コンソールから定数/変数名を入力するとアクセスできてしまいます。 +// ブロック内に入れてスコープを非グローバル化するとそれが防げます +// (Chrome以外のブラウザでは検証していません) +{ + // Get the current url information + const url = new URL(location.href); + + //#region Detect app name + let app = null; + + if (url.pathname == '/docs') app = 'docs'; + if (url.pathname == '/dev') app = 'dev'; + if (url.pathname == '/auth') app = 'auth'; + //#endregion + + // Detect the user language + // Note: The default language is English + let lang = navigator.language.split('-')[0]; + if (!/^(en|ja)$/.test(lang)) lang = 'en'; + if (localStorage.getItem('lang')) lang = localStorage.getItem('lang'); + if (ENV != 'production') lang = 'ja'; + + // Detect the user agent + const ua = navigator.userAgent.toLowerCase(); + const isMobile = /mobile|iphone|ipad|android/.test(ua); + + // Get the element + const head = document.getElementsByTagName('head')[0]; + + // If mobile, insert the viewport meta tag + if (isMobile) { + const meta = document.createElement('meta'); + meta.setAttribute('name', 'viewport'); + meta.setAttribute('content', + 'width=device-width,' + + 'initial-scale=1,' + + 'minimum-scale=1,' + + 'maximum-scale=1,' + + 'user-scalable=no'); + head.appendChild(meta); + } + + // Switch desktop or mobile version + if (app == null) { + app = isMobile ? 'mobile' : 'desktop'; + } + + // Script version + const ver = localStorage.getItem('v') || VERSION; + + // Whether in debug mode + const isDebug = localStorage.getItem('debug') == 'true'; + + // Whether use raw version script + const raw = (localStorage.getItem('useRawScript') == 'true' && isDebug) + || ENV != 'production'; + + // Load an app script + // Note: 'async' make it possible to load the script asyncly. + // 'defer' make it possible to run the script when the dom loaded. + const script = document.createElement('script'); + script.setAttribute('src', `/assets/${app}.${ver}.${lang}.${raw ? 'raw' : 'min'}.js`); + script.setAttribute('async', 'true'); + script.setAttribute('defer', 'true'); + head.appendChild(script); + + // 1秒経ってもスクリプトがロードされない場合はバージョンが古くて + // 404になっているせいかもしれないので、バージョンを確認して古ければ更新する + // + // 読み込まれたスクリプトからこのタイマーを解除できるように、 + // グローバルにタイマーIDを代入しておく + window.mkBootTimer = window.setTimeout(async () => { + // Fetch meta + const res = await fetch(API + '/meta', { + method: 'POST', + cache: 'no-cache' + }); + + // Parse + const meta = await res.json(); + + // Compare versions + if (meta.version != ver) { + alert( + 'Misskeyの新しいバージョンがあります。ページを再度読み込みします。' + + '\n\n' + + 'New version of Misskey available. The page will be reloaded.'); + + // Clear cache (serive worker) + try { + navigator.serviceWorker.controller.postMessage('clear'); + + navigator.serviceWorker.getRegistrations().then(registrations => { + registrations.forEach(registration => registration.unregister()); + }); + } catch (e) { + console.error(e); + } + + // Force reload + location.reload(true); + } + }, 1000); +} diff --git a/src/server/web/app/ch/script.ts b/src/server/web/app/ch/script.ts new file mode 100644 index 0000000000..4c6b6dfd1b --- /dev/null +++ b/src/server/web/app/ch/script.ts @@ -0,0 +1,15 @@ +/** + * Channels + */ + +// Style +import './style.styl'; + +require('./tags'); +import init from '../init'; + +/** + * init + */ +init(() => { +}); diff --git a/src/server/web/app/ch/style.styl b/src/server/web/app/ch/style.styl new file mode 100644 index 0000000000..21ca648cbe --- /dev/null +++ b/src/server/web/app/ch/style.styl @@ -0,0 +1,10 @@ +@import "../app" + +html + padding 8px + background #efefef + +#wait + top auto + bottom 15px + left 15px diff --git a/src/server/web/app/ch/tags/channel.tag b/src/server/web/app/ch/tags/channel.tag new file mode 100644 index 0000000000..dc4b8e1426 --- /dev/null +++ b/src/server/web/app/ch/tags/channel.tag @@ -0,0 +1,403 @@ + + +
    +
    +

    { channel.title }

    + +
    +

    このチャンネルをウォッチしています ウォッチ解除

    +

    このチャンネルをウォッチする

    +
    + + + +
    +

    読み込み中

    +
    +

    まだ投稿がありません

    + +
    +
    +
    + +
    +

    参加するにはログインまたは新規登録してください

    +
    +
    +
    + Misskey ver { _VERSION_ } (葵 aoi) +
    +
    + + +
    + + +
    + { post.index }: + { post.user.name } + + + ID:{ acct } +
    +
    + >>{ post.reply.index } + { post.text } +
    + +
    +
    + + +
    + + +

    >>{ reply.index } ({ reply.user.name }): [x]

    + +
    + + + +
    + +
      +
    1. { name }
    2. +
    + + + +
    + + + + + + + + + + diff --git a/src/server/web/app/ch/tags/header.tag b/src/server/web/app/ch/tags/header.tag new file mode 100644 index 0000000000..901123d63b --- /dev/null +++ b/src/server/web/app/ch/tags/header.tag @@ -0,0 +1,20 @@ + +
    + Index | Misskey +
    + + + +
    diff --git a/src/server/web/app/ch/tags/index.tag b/src/server/web/app/ch/tags/index.tag new file mode 100644 index 0000000000..88df2ec45d --- /dev/null +++ b/src/server/web/app/ch/tags/index.tag @@ -0,0 +1,37 @@ + + +
    + +
    + + + +
    diff --git a/src/server/web/app/ch/tags/index.ts b/src/server/web/app/ch/tags/index.ts new file mode 100644 index 0000000000..12ffdaeb84 --- /dev/null +++ b/src/server/web/app/ch/tags/index.ts @@ -0,0 +1,3 @@ +require('./index.tag'); +require('./channel.tag'); +require('./header.tag'); diff --git a/src/server/web/app/common/define-widget.ts b/src/server/web/app/common/define-widget.ts new file mode 100644 index 0000000000..d8d29873a4 --- /dev/null +++ b/src/server/web/app/common/define-widget.ts @@ -0,0 +1,79 @@ +import Vue from 'vue'; + +export default function(data: { + name: string; + props?: () => T; +}) { + return Vue.extend({ + props: { + widget: { + type: Object + }, + isMobile: { + type: Boolean, + default: false + }, + isCustomizeMode: { + type: Boolean, + default: false + } + }, + computed: { + id(): string { + return this.widget.id; + } + }, + data() { + return { + props: data.props ? data.props() : {} as T, + bakedOldProps: null, + preventSave: false + }; + }, + created() { + if (this.props) { + Object.keys(this.props).forEach(prop => { + if (this.widget.data.hasOwnProperty(prop)) { + this.props[prop] = this.widget.data[prop]; + } + }); + } + + this.bakeProps(); + + this.$watch('props', newProps => { + if (this.preventSave) { + this.preventSave = false; + this.bakeProps(); + return; + } + if (this.bakedOldProps == JSON.stringify(newProps)) return; + + this.bakeProps(); + + if (this.isMobile) { + (this as any).api('i/update_mobile_home', { + id: this.id, + data: newProps + }).then(() => { + (this as any).os.i.account.client_settings.mobile_home.find(w => w.id == this.id).data = newProps; + }); + } else { + (this as any).api('i/update_home', { + id: this.id, + data: newProps + }).then(() => { + (this as any).os.i.account.client_settings.home.find(w => w.id == this.id).data = newProps; + }); + } + }, { + deep: true + }); + }, + methods: { + bakeProps() { + this.bakedOldProps = JSON.stringify(this.props); + } + } + }); +} diff --git a/src/server/web/app/common/mios.ts b/src/server/web/app/common/mios.ts new file mode 100644 index 0000000000..2c6c9988e7 --- /dev/null +++ b/src/server/web/app/common/mios.ts @@ -0,0 +1,578 @@ +import Vue from 'vue'; +import { EventEmitter } from 'eventemitter3'; +import * as merge from 'object-assign-deep'; +import * as uuid from 'uuid'; + +import { hostname, apiUrl, swPublickey, version, lang, googleMapsApiKey } from '../config'; +import Progress from './scripts/loading'; +import Connection from './scripts/streaming/stream'; +import { HomeStreamManager } from './scripts/streaming/home'; +import { DriveStreamManager } from './scripts/streaming/drive'; +import { ServerStreamManager } from './scripts/streaming/server'; +import { RequestsStreamManager } from './scripts/streaming/requests'; +import { MessagingIndexStreamManager } from './scripts/streaming/messaging-index'; +import { OthelloStreamManager } from './scripts/streaming/othello'; + +import Err from '../common/views/components/connect-failed.vue'; + +//#region api requests +let spinner = null; +let pending = 0; +//#endregion + +export type API = { + chooseDriveFile: (opts: { + title?: string; + currentFolder?: any; + multiple?: boolean; + }) => Promise; + + chooseDriveFolder: (opts: { + title?: string; + currentFolder?: any; + }) => Promise; + + dialog: (opts: { + title: string; + text: string; + actions?: Array<{ + text: string; + id?: string; + }>; + }) => Promise; + + input: (opts: { + title: string; + placeholder?: string; + default?: string; + }) => Promise; + + post: (opts?: { + reply?: any; + repost?: any; + }) => void; + + notify: (message: string) => void; +}; + +/** + * Misskey Operating System + */ +export default class MiOS extends EventEmitter { + /** + * Misskeyの /meta で取得できるメタ情報 + */ + private meta: { + data: { [x: string]: any }; + chachedAt: Date; + }; + + private isMetaFetching = false; + + public app: Vue; + + public new(vm, props) { + const w = new vm({ + parent: this.app, + propsData: props + }).$mount(); + document.body.appendChild(w.$el); + } + + /** + * A signing user + */ + public i: { [x: string]: any }; + + /** + * Whether signed in + */ + public get isSignedIn() { + return this.i != null; + } + + /** + * Whether is debug mode + */ + public get debug() { + return localStorage.getItem('debug') == 'true'; + } + + /** + * Whether enable sounds + */ + public get isEnableSounds() { + return localStorage.getItem('enableSounds') == 'true'; + } + + public apis: API; + + /** + * A connection manager of home stream + */ + public stream: HomeStreamManager; + + /** + * Connection managers + */ + public streams: { + driveStream: DriveStreamManager; + serverStream: ServerStreamManager; + requestsStream: RequestsStreamManager; + messagingIndexStream: MessagingIndexStreamManager; + othelloStream: OthelloStreamManager; + } = { + driveStream: null, + serverStream: null, + requestsStream: null, + messagingIndexStream: null, + othelloStream: null + }; + + /** + * A registration of service worker + */ + private swRegistration: ServiceWorkerRegistration = null; + + /** + * Whether should register ServiceWorker + */ + private shouldRegisterSw: boolean; + + /** + * ウィンドウシステム + */ + public windows = new WindowSystem(); + + /** + * MiOSインスタンスを作成します + * @param shouldRegisterSw ServiceWorkerを登録するかどうか + */ + constructor(shouldRegisterSw = false) { + super(); + + this.shouldRegisterSw = shouldRegisterSw; + + //#region BIND + this.log = this.log.bind(this); + this.logInfo = this.logInfo.bind(this); + this.logWarn = this.logWarn.bind(this); + this.logError = this.logError.bind(this); + this.init = this.init.bind(this); + this.api = this.api.bind(this); + this.getMeta = this.getMeta.bind(this); + this.registerSw = this.registerSw.bind(this); + //#endregion + + if (this.debug) { + (window as any).os = this; + } + } + + private googleMapsIniting = false; + + public getGoogleMaps() { + return new Promise((res, rej) => { + if ((window as any).google && (window as any).google.maps) { + res((window as any).google.maps); + } else { + this.once('init-google-maps', () => { + res((window as any).google.maps); + }); + + //#region load google maps api + if (!this.googleMapsIniting) { + this.googleMapsIniting = true; + (window as any).initGoogleMaps = () => { + this.emit('init-google-maps'); + }; + const head = document.getElementsByTagName('head')[0]; + const script = document.createElement('script'); + script.setAttribute('src', `https://maps.googleapis.com/maps/api/js?key=${googleMapsApiKey}&callback=initGoogleMaps`); + script.setAttribute('async', 'true'); + script.setAttribute('defer', 'true'); + head.appendChild(script); + } + //#endregion + } + }); + } + + public log(...args) { + if (!this.debug) return; + console.log.apply(null, args); + } + + public logInfo(...args) { + if (!this.debug) return; + console.info.apply(null, args); + } + + public logWarn(...args) { + if (!this.debug) return; + console.warn.apply(null, args); + } + + public logError(...args) { + if (!this.debug) return; + console.error.apply(null, args); + } + + public signout() { + localStorage.removeItem('me'); + document.cookie = `i=; domain=.${hostname}; expires=Thu, 01 Jan 1970 00:00:01 GMT;`; + location.href = '/'; + } + + /** + * Initialize MiOS (boot) + * @param callback A function that call when initialized + */ + public async init(callback) { + //#region Init stream managers + this.streams.serverStream = new ServerStreamManager(this); + this.streams.requestsStream = new RequestsStreamManager(this); + + this.once('signedin', () => { + // Init home stream manager + this.stream = new HomeStreamManager(this, this.i); + + // Init other stream manager + this.streams.driveStream = new DriveStreamManager(this, this.i); + this.streams.messagingIndexStream = new MessagingIndexStreamManager(this, this.i); + this.streams.othelloStream = new OthelloStreamManager(this, this.i); + }); + //#endregion + + // ユーザーをフェッチしてコールバックする + const fetchme = (token, cb) => { + let me = null; + + // Return when not signed in + if (token == null) { + return done(); + } + + // Fetch user + fetch(`${apiUrl}/i`, { + method: 'POST', + body: JSON.stringify({ + i: token + }) + }) + // When success + .then(res => { + // When failed to authenticate user + if (res.status !== 200) { + return this.signout(); + } + + // Parse response + res.json().then(i => { + me = i; + me.account.token = token; + done(); + }); + }) + // When failure + .catch(() => { + // Render the error screen + document.body.innerHTML = '
    '; + new Vue({ + render: createEl => createEl(Err) + }).$mount('#err'); + + Progress.done(); + }); + + function done() { + if (cb) cb(me); + } + }; + + // フェッチが完了したとき + const fetched = me => { + if (me) { + // デフォルトの設定をマージ + me.account.client_settings = Object.assign({ + fetchOnScroll: true, + showMaps: true, + showPostFormOnTopOfTl: false, + gradientWindowHeader: false + }, me.account.client_settings); + + // ローカルストレージにキャッシュ + localStorage.setItem('me', JSON.stringify(me)); + } + + this.i = me; + + this.emit('signedin'); + + // Finish init + callback(); + + //#region Post + + // Init service worker + if (this.shouldRegisterSw) this.registerSw(); + + //#endregion + }; + + // Get cached account data + const cachedMe = JSON.parse(localStorage.getItem('me')); + + // キャッシュがあったとき + if (cachedMe) { + // とりあえずキャッシュされたデータでお茶を濁して(?)おいて、 + fetched(cachedMe); + + // 後から新鮮なデータをフェッチ + fetchme(cachedMe.account.token, freshData => { + merge(cachedMe, freshData); + }); + } else { + // Get token from cookie + const i = (document.cookie.match(/i=(!\w+)/) || [null, null])[1]; + + fetchme(i, fetched); + } + } + + /** + * Register service worker + */ + private registerSw() { + // Check whether service worker and push manager supported + const isSwSupported = + ('serviceWorker' in navigator) && ('PushManager' in window); + + // Reject when browser not service worker supported + if (!isSwSupported) return; + + // Reject when not signed in to Misskey + if (!this.isSignedIn) return; + + // When service worker activated + navigator.serviceWorker.ready.then(registration => { + this.log('[sw] ready: ', registration); + + this.swRegistration = registration; + + // Options of pushManager.subscribe + // SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters + const opts = { + // A boolean indicating that the returned push subscription + // will only be used for messages whose effect is made visible to the user. + userVisibleOnly: true, + + // A public key your push server will use to send + // messages to client apps via a push server. + applicationServerKey: urlBase64ToUint8Array(swPublickey) + }; + + // Subscribe push notification + this.swRegistration.pushManager.subscribe(opts).then(subscription => { + this.log('[sw] Subscribe OK:', subscription); + + function encode(buffer: ArrayBuffer) { + return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer))); + } + + // Register + this.api('sw/register', { + endpoint: subscription.endpoint, + auth: encode(subscription.getKey('auth')), + publickey: encode(subscription.getKey('p256dh')) + }); + }) + // When subscribe failed + .catch(async (err: Error) => { + this.logError('[sw] Subscribe Error:', err); + + // 通知が許可されていなかったとき + if (err.name == 'NotAllowedError') { + this.logError('[sw] Subscribe failed due to notification not allowed'); + return; + } + + // 違うapplicationServerKey (または gcm_sender_id)のサブスクリプションが + // 既に存在していることが原因でエラーになった可能性があるので、 + // そのサブスクリプションを解除しておく + const subscription = await this.swRegistration.pushManager.getSubscription(); + if (subscription) subscription.unsubscribe(); + }); + }); + + // Whether use raw version script + const raw = (localStorage.getItem('useRawScript') == 'true' && this.debug) + || process.env.NODE_ENV != 'production'; + + // The path of service worker script + const sw = `/sw.${version}.${lang}.${raw ? 'raw' : 'min'}.js`; + + // Register service worker + navigator.serviceWorker.register(sw).then(registration => { + // 登録成功 + this.logInfo('[sw] Registration successful with scope: ', registration.scope); + }).catch(err => { + // 登録失敗 :( + this.logError('[sw] Registration failed: ', err); + }); + } + + public requests = []; + + /** + * Misskey APIにリクエストします + * @param endpoint エンドポイント名 + * @param data パラメータ + */ + public api(endpoint: string, data: { [x: string]: any } = {}): Promise<{ [x: string]: any }> { + if (++pending === 1) { + spinner = document.createElement('div'); + spinner.setAttribute('id', 'wait'); + document.body.appendChild(spinner); + } + + // Append a credential + if (this.isSignedIn) (data as any).i = this.i.account.token; + + // TODO + //const viaStream = localStorage.getItem('enableExperimental') == 'true'; + + return new Promise((resolve, reject) => { + /*if (viaStream) { + const stream = this.stream.borrow(); + const id = Math.random().toString(); + stream.once(`api-res:${id}`, res => { + resolve(res); + }); + stream.send({ + type: 'api', + id, + endpoint, + data + }); + } else {*/ + const req = { + id: uuid(), + date: new Date(), + name: endpoint, + data, + res: null, + status: null + }; + + if (this.debug) { + this.requests.push(req); + } + + // Send request + fetch(endpoint.indexOf('://') > -1 ? endpoint : `${apiUrl}/${endpoint}`, { + method: 'POST', + body: JSON.stringify(data), + credentials: endpoint === 'signin' ? 'include' : 'omit', + cache: 'no-cache' + }).then(async (res) => { + if (--pending === 0) spinner.parentNode.removeChild(spinner); + + const body = res.status === 204 ? null : await res.json(); + + if (this.debug) { + req.status = res.status; + req.res = body; + } + + if (res.status === 200) { + resolve(body); + } else if (res.status === 204) { + resolve(); + } else { + reject(body.error); + } + }).catch(reject); + /*}*/ + }); + } + + /** + * Misskeyのメタ情報を取得します + * @param force キャッシュを無視するか否か + */ + public getMeta(force = false) { + return new Promise<{ [x: string]: any }>(async (res, rej) => { + if (this.isMetaFetching) { + this.once('_meta_fetched_', () => { + res(this.meta.data); + }); + return; + } + + const expire = 1000 * 60; // 1min + + // forceが有効, meta情報を保持していない or 期限切れ + if (force || this.meta == null || Date.now() - this.meta.chachedAt.getTime() > expire) { + this.isMetaFetching = true; + const meta = await this.api('meta'); + this.meta = { + data: meta, + chachedAt: new Date() + }; + this.isMetaFetching = false; + this.emit('_meta_fetched_'); + res(meta); + } else { + res(this.meta.data); + } + }); + } + + public connections: Connection[] = []; + + public registerStreamConnection(connection: Connection) { + this.connections.push(connection); + } + + public unregisterStreamConnection(connection: Connection) { + this.connections = this.connections.filter(c => c != connection); + } +} + +class WindowSystem extends EventEmitter { + public windows = new Set(); + + public add(window) { + this.windows.add(window); + this.emit('added', window); + } + + public remove(window) { + this.windows.delete(window); + this.emit('removed', window); + } + + public getAll() { + return this.windows; + } +} + +/** + * Convert the URL safe base64 string to a Uint8Array + * @param base64String base64 string + */ +function urlBase64ToUint8Array(base64String: string): Uint8Array { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding) + .replace(/\-/g, '+') + .replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} diff --git a/src/server/web/app/common/scripts/check-for-update.ts b/src/server/web/app/common/scripts/check-for-update.ts new file mode 100644 index 0000000000..81c1eb9812 --- /dev/null +++ b/src/server/web/app/common/scripts/check-for-update.ts @@ -0,0 +1,33 @@ +import MiOS from '../mios'; +import { version as current } from '../../config'; + +export default async function(mios: MiOS, force = false, silent = false) { + const meta = await mios.getMeta(force); + const newer = meta.version; + + if (newer != current) { + localStorage.setItem('should-refresh', 'true'); + localStorage.setItem('v', newer); + + // Clear cache (serive worker) + try { + if (navigator.serviceWorker.controller) { + navigator.serviceWorker.controller.postMessage('clear'); + } + + navigator.serviceWorker.getRegistrations().then(registrations => { + registrations.forEach(registration => registration.unregister()); + }); + } catch (e) { + console.error(e); + } + + if (!silent) { + alert('%i18n:common.update-available%'.replace('{newer}', newer).replace('{current}', current)); + } + + return newer; + } else { + return null; + } +} diff --git a/src/server/web/app/common/scripts/compose-notification.ts b/src/server/web/app/common/scripts/compose-notification.ts new file mode 100644 index 0000000000..e1dbd3bc13 --- /dev/null +++ b/src/server/web/app/common/scripts/compose-notification.ts @@ -0,0 +1,67 @@ +import getPostSummary from '../../../../common/get-post-summary'; +import getReactionEmoji from '../../../../common/get-reaction-emoji'; + +type Notification = { + title: string; + body: string; + icon: string; + onclick?: any; +}; + +// TODO: i18n + +export default function(type, data): Notification { + switch (type) { + case 'drive_file_created': + return { + title: 'ファイルがアップロードされました', + body: data.name, + icon: data.url + '?thumbnail&size=64' + }; + + case 'mention': + return { + title: `${data.user.name}さんから:`, + body: getPostSummary(data), + icon: data.user.avatar_url + '?thumbnail&size=64' + }; + + case 'reply': + return { + title: `${data.user.name}さんから返信:`, + body: getPostSummary(data), + icon: data.user.avatar_url + '?thumbnail&size=64' + }; + + case 'quote': + return { + title: `${data.user.name}さんが引用:`, + body: getPostSummary(data), + icon: data.user.avatar_url + '?thumbnail&size=64' + }; + + case 'reaction': + return { + title: `${data.user.name}: ${getReactionEmoji(data.reaction)}:`, + body: getPostSummary(data.post), + icon: data.user.avatar_url + '?thumbnail&size=64' + }; + + case 'unread_messaging_message': + return { + title: `${data.user.name}さんからメッセージ:`, + body: data.text, // TODO: getMessagingMessageSummary(data), + icon: data.user.avatar_url + '?thumbnail&size=64' + }; + + case 'othello_invited': + return { + title: '対局への招待があります', + body: `${data.parent.name}さんから`, + icon: data.parent.avatar_url + '?thumbnail&size=64' + }; + + default: + return null; + } +} diff --git a/src/server/web/app/common/scripts/contains.ts b/src/server/web/app/common/scripts/contains.ts new file mode 100644 index 0000000000..a5071b3f25 --- /dev/null +++ b/src/server/web/app/common/scripts/contains.ts @@ -0,0 +1,8 @@ +export default (parent, child) => { + let node = child.parentNode; + while (node) { + if (node == parent) return true; + node = node.parentNode; + } + return false; +}; diff --git a/src/server/web/app/common/scripts/copy-to-clipboard.ts b/src/server/web/app/common/scripts/copy-to-clipboard.ts new file mode 100644 index 0000000000..3d2741f8d7 --- /dev/null +++ b/src/server/web/app/common/scripts/copy-to-clipboard.ts @@ -0,0 +1,13 @@ +/** + * Clipboardに値をコピー(TODO: 文字列以外も対応) + */ +export default val => { + const form = document.createElement('textarea'); + form.textContent = val; + document.body.appendChild(form); + form.select(); + const result = document.execCommand('copy'); + document.body.removeChild(form); + + return result; +}; diff --git a/src/server/web/app/common/scripts/date-stringify.ts b/src/server/web/app/common/scripts/date-stringify.ts new file mode 100644 index 0000000000..e51de8833d --- /dev/null +++ b/src/server/web/app/common/scripts/date-stringify.ts @@ -0,0 +1,13 @@ +export default date => { + if (typeof date == 'string') date = new Date(date); + return ( + date.getFullYear() + '年' + + (date.getMonth() + 1) + '月' + + date.getDate() + '日' + + ' ' + + date.getHours() + '時' + + date.getMinutes() + '分' + + ' ' + + `(${['日', '月', '火', '水', '木', '金', '土'][date.getDay()]})` + ); +}; diff --git a/src/server/web/app/common/scripts/fuck-ad-block.ts b/src/server/web/app/common/scripts/fuck-ad-block.ts new file mode 100644 index 0000000000..9bcf7deeff --- /dev/null +++ b/src/server/web/app/common/scripts/fuck-ad-block.ts @@ -0,0 +1,21 @@ +require('fuckadblock'); + +declare const fuckAdBlock: any; + +export default (os) => { + function adBlockDetected() { + os.apis.dialog({ + title: '%fa:exclamation-triangle%広告ブロッカーを無効にしてください', + text: 'Misskeyは広告を掲載していませんが、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。', + actins: [{ + text: 'OK' + }] + }); + } + + if (fuckAdBlock === undefined) { + adBlockDetected(); + } else { + fuckAdBlock.onDetected(adBlockDetected); + } +}; diff --git a/src/server/web/app/common/scripts/gcd.ts b/src/server/web/app/common/scripts/gcd.ts new file mode 100644 index 0000000000..9a19f9da66 --- /dev/null +++ b/src/server/web/app/common/scripts/gcd.ts @@ -0,0 +1,2 @@ +const gcd = (a, b) => !b ? a : gcd(b, a % b); +export default gcd; diff --git a/src/server/web/app/common/scripts/get-kao.ts b/src/server/web/app/common/scripts/get-kao.ts new file mode 100644 index 0000000000..2168c5be88 --- /dev/null +++ b/src/server/web/app/common/scripts/get-kao.ts @@ -0,0 +1,5 @@ +export default () => [ + '(=^・・^=)', + 'v(‘ω’)v', + '🐡( \'-\' 🐡 )フグパンチ!!!!' +][Math.floor(Math.random() * 3)]; diff --git a/src/server/web/app/common/scripts/get-median.ts b/src/server/web/app/common/scripts/get-median.ts new file mode 100644 index 0000000000..91a415d5b2 --- /dev/null +++ b/src/server/web/app/common/scripts/get-median.ts @@ -0,0 +1,11 @@ +/** + * 中央値を求めます + * @param samples サンプル + */ +export default function(samples) { + if (!samples.length) return 0; + const numbers = samples.slice(0).sort((a, b) => a - b); + const middle = Math.floor(numbers.length / 2); + const isEven = numbers.length % 2 === 0; + return isEven ? (numbers[middle] + numbers[middle - 1]) / 2 : numbers[middle]; +} diff --git a/src/server/web/app/common/scripts/loading.ts b/src/server/web/app/common/scripts/loading.ts new file mode 100644 index 0000000000..c48e626648 --- /dev/null +++ b/src/server/web/app/common/scripts/loading.ts @@ -0,0 +1,21 @@ +const NProgress = require('nprogress'); +NProgress.configure({ + trickleSpeed: 500, + showSpinner: false +}); + +const root = document.getElementsByTagName('html')[0]; + +export default { + start: () => { + root.classList.add('progress'); + NProgress.start(); + }, + done: () => { + root.classList.remove('progress'); + NProgress.done(); + }, + set: val => { + NProgress.set(val); + } +}; diff --git a/src/server/web/app/common/scripts/parse-search-query.ts b/src/server/web/app/common/scripts/parse-search-query.ts new file mode 100644 index 0000000000..512791ecb0 --- /dev/null +++ b/src/server/web/app/common/scripts/parse-search-query.ts @@ -0,0 +1,53 @@ +export default function(qs: string) { + const q = { + text: '' + }; + + qs.split(' ').forEach(x => { + if (/^([a-z_]+?):(.+?)$/.test(x)) { + const [key, value] = x.split(':'); + switch (key) { + case 'user': + q['include_user_usernames'] = value.split(','); + break; + case 'exclude_user': + q['exclude_user_usernames'] = value.split(','); + break; + case 'follow': + q['following'] = value == 'null' ? null : value == 'true'; + break; + case 'reply': + q['reply'] = value == 'null' ? null : value == 'true'; + break; + case 'repost': + q['repost'] = value == 'null' ? null : value == 'true'; + break; + case 'media': + q['media'] = value == 'null' ? null : value == 'true'; + break; + case 'poll': + q['poll'] = value == 'null' ? null : value == 'true'; + break; + case 'until': + case 'since': + // YYYY-MM-DD + if (/^[0-9]+\-[0-9]+\-[0-9]+$/) { + const [yyyy, mm, dd] = value.split('-'); + q[`${key}_date`] = (new Date(parseInt(yyyy, 10), parseInt(mm, 10) - 1, parseInt(dd, 10))).getTime(); + } + break; + default: + q[key] = value; + break; + } + } else { + q.text += x + ' '; + } + }); + + if (q.text) { + q.text = q.text.trim(); + } + + return q; +} diff --git a/src/server/web/app/common/scripts/streaming/channel.ts b/src/server/web/app/common/scripts/streaming/channel.ts new file mode 100644 index 0000000000..cab5f4edb4 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/channel.ts @@ -0,0 +1,13 @@ +import Stream from './stream'; +import MiOS from '../../mios'; + +/** + * Channel stream connection + */ +export default class Connection extends Stream { + constructor(os: MiOS, channelId) { + super(os, 'channel', { + channel: channelId + }); + } +} diff --git a/src/server/web/app/common/scripts/streaming/drive.ts b/src/server/web/app/common/scripts/streaming/drive.ts new file mode 100644 index 0000000000..f11573685e --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/drive.ts @@ -0,0 +1,34 @@ +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../mios'; + +/** + * Drive stream connection + */ +export class DriveStream extends Stream { + constructor(os: MiOS, me) { + super(os, 'drive', { + i: me.account.token + }); + } +} + +export class DriveStreamManager extends StreamManager { + private me; + private os: MiOS; + + constructor(os: MiOS, me) { + super(); + + this.me = me; + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new DriveStream(this.os, this.me); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/home.ts b/src/server/web/app/common/scripts/streaming/home.ts new file mode 100644 index 0000000000..ffcf6e5360 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/home.ts @@ -0,0 +1,57 @@ +import * as merge from 'object-assign-deep'; + +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../mios'; + +/** + * Home stream connection + */ +export class HomeStream extends Stream { + constructor(os: MiOS, me) { + super(os, '', { + i: me.account.token + }); + + // 最終利用日時を更新するため定期的にaliveメッセージを送信 + setInterval(() => { + this.send({ type: 'alive' }); + me.account.last_used_at = new Date(); + }, 1000 * 60); + + // 自分の情報が更新されたとき + this.on('i_updated', i => { + if (os.debug) { + console.log('I updated:', i); + } + merge(me, i); + }); + + // トークンが再生成されたとき + // このままではAPIが利用できないので強制的にサインアウトさせる + this.on('my_token_regenerated', () => { + alert('%i18n:common.my-token-regenerated%'); + os.signout(); + }); + } +} + +export class HomeStreamManager extends StreamManager { + private me; + private os: MiOS; + + constructor(os: MiOS, me) { + super(); + + this.me = me; + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new HomeStream(this.os, this.me); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/messaging-index.ts b/src/server/web/app/common/scripts/streaming/messaging-index.ts new file mode 100644 index 0000000000..24f0ce0c9f --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/messaging-index.ts @@ -0,0 +1,34 @@ +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../mios'; + +/** + * Messaging index stream connection + */ +export class MessagingIndexStream extends Stream { + constructor(os: MiOS, me) { + super(os, 'messaging-index', { + i: me.account.token + }); + } +} + +export class MessagingIndexStreamManager extends StreamManager { + private me; + private os: MiOS; + + constructor(os: MiOS, me) { + super(); + + this.me = me; + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new MessagingIndexStream(this.os, this.me); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/messaging.ts b/src/server/web/app/common/scripts/streaming/messaging.ts new file mode 100644 index 0000000000..4c593deb31 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/messaging.ts @@ -0,0 +1,20 @@ +import Stream from './stream'; +import MiOS from '../../mios'; + +/** + * Messaging stream connection + */ +export class MessagingStream extends Stream { + constructor(os: MiOS, me, otherparty) { + super(os, 'messaging', { + i: me.account.token, + otherparty + }); + + (this as any).on('_connected_', () => { + this.send({ + i: me.account.token + }); + }); + } +} diff --git a/src/server/web/app/common/scripts/streaming/othello-game.ts b/src/server/web/app/common/scripts/streaming/othello-game.ts new file mode 100644 index 0000000000..f34ef35147 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/othello-game.ts @@ -0,0 +1,11 @@ +import Stream from './stream'; +import MiOS from '../../mios'; + +export class OthelloGameStream extends Stream { + constructor(os: MiOS, me, game) { + super(os, 'othello-game', { + i: me ? me.account.token : null, + game: game.id + }); + } +} diff --git a/src/server/web/app/common/scripts/streaming/othello.ts b/src/server/web/app/common/scripts/streaming/othello.ts new file mode 100644 index 0000000000..8c6f4b9c3c --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/othello.ts @@ -0,0 +1,31 @@ +import StreamManager from './stream-manager'; +import Stream from './stream'; +import MiOS from '../../mios'; + +export class OthelloStream extends Stream { + constructor(os: MiOS, me) { + super(os, 'othello', { + i: me.account.token + }); + } +} + +export class OthelloStreamManager extends StreamManager { + private me; + private os: MiOS; + + constructor(os: MiOS, me) { + super(); + + this.me = me; + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new OthelloStream(this.os, this.me); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/requests.ts b/src/server/web/app/common/scripts/streaming/requests.ts new file mode 100644 index 0000000000..5bec30143f --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/requests.ts @@ -0,0 +1,30 @@ +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../mios'; + +/** + * Requests stream connection + */ +export class RequestsStream extends Stream { + constructor(os: MiOS) { + super(os, 'requests'); + } +} + +export class RequestsStreamManager extends StreamManager { + private os: MiOS; + + constructor(os: MiOS) { + super(); + + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new RequestsStream(this.os); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/server.ts b/src/server/web/app/common/scripts/streaming/server.ts new file mode 100644 index 0000000000..3d35ef4d9d --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/server.ts @@ -0,0 +1,30 @@ +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../mios'; + +/** + * Server stream connection + */ +export class ServerStream extends Stream { + constructor(os: MiOS) { + super(os, 'server'); + } +} + +export class ServerStreamManager extends StreamManager { + private os: MiOS; + + constructor(os: MiOS) { + super(); + + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new ServerStream(this.os); + } + + return this.connection; + } +} diff --git a/src/server/web/app/common/scripts/streaming/stream-manager.ts b/src/server/web/app/common/scripts/streaming/stream-manager.ts new file mode 100644 index 0000000000..568b8b0372 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/stream-manager.ts @@ -0,0 +1,108 @@ +import { EventEmitter } from 'eventemitter3'; +import * as uuid from 'uuid'; +import Connection from './stream'; + +/** + * ストリーム接続を管理するクラス + * 複数の場所から同じストリームを利用する際、接続をまとめたりする + */ +export default abstract class StreamManager extends EventEmitter { + private _connection: T = null; + + private disposeTimerId: any; + + /** + * コネクションを必要としているユーザー + */ + private users = []; + + protected set connection(connection: T) { + this._connection = connection; + + if (this._connection == null) { + this.emit('disconnected'); + } else { + this.emit('connected', this._connection); + + this._connection.on('_connected_', () => { + this.emit('_connected_'); + }); + + this._connection.on('_disconnected_', () => { + this.emit('_disconnected_'); + }); + + this._connection.user = 'Managed'; + } + } + + protected get connection() { + return this._connection; + } + + /** + * コネクションを持っているか否か + */ + public get hasConnection() { + return this._connection != null; + } + + public get state(): string { + if (!this.hasConnection) return 'no-connection'; + return this._connection.state; + } + + /** + * コネクションを要求します + */ + public abstract getConnection(): T; + + /** + * 現在接続しているコネクションを取得します + */ + public borrow() { + return this._connection; + } + + /** + * コネクションを要求するためのユーザーIDを発行します + */ + public use() { + // タイマー解除 + if (this.disposeTimerId) { + clearTimeout(this.disposeTimerId); + this.disposeTimerId = null; + } + + // ユーザーID生成 + const userId = uuid(); + + this.users.push(userId); + + this._connection.user = `Managed (${ this.users.length })`; + + return userId; + } + + /** + * コネクションを利用し終わってもう必要ないことを通知します + * @param userId use で発行したユーザーID + */ + public dispose(userId) { + this.users = this.users.filter(id => id != userId); + + this._connection.user = `Managed (${ this.users.length })`; + + // 誰もコネクションの利用者がいなくなったら + if (this.users.length == 0) { + // また直ぐに再利用される可能性があるので、一定時間待ち、 + // 新たな利用者が現れなければコネクションを切断する + this.disposeTimerId = setTimeout(() => { + this.disposeTimerId = null; + + this.connection.close(); + this.connection = null; + }, 3000); + } + } +} diff --git a/src/server/web/app/common/scripts/streaming/stream.ts b/src/server/web/app/common/scripts/streaming/stream.ts new file mode 100644 index 0000000000..3912186ad3 --- /dev/null +++ b/src/server/web/app/common/scripts/streaming/stream.ts @@ -0,0 +1,137 @@ +import { EventEmitter } from 'eventemitter3'; +import * as uuid from 'uuid'; +import * as ReconnectingWebsocket from 'reconnecting-websocket'; +import { wsUrl } from '../../../config'; +import MiOS from '../../mios'; + +/** + * Misskey stream connection + */ +export default class Connection extends EventEmitter { + public state: string; + private buffer: any[]; + public socket: ReconnectingWebsocket; + public name: string; + public connectedAt: Date; + public user: string = null; + public in: number = 0; + public out: number = 0; + public inout: Array<{ + type: 'in' | 'out', + at: Date, + data: string + }> = []; + public id: string; + public isSuspended = false; + private os: MiOS; + + constructor(os: MiOS, endpoint, params?) { + super(); + + //#region BIND + this.onOpen = this.onOpen.bind(this); + this.onClose = this.onClose.bind(this); + this.onMessage = this.onMessage.bind(this); + this.send = this.send.bind(this); + this.close = this.close.bind(this); + //#endregion + + this.id = uuid(); + this.os = os; + this.name = endpoint; + this.state = 'initializing'; + this.buffer = []; + + const query = params + ? Object.keys(params) + .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])) + .join('&') + : null; + + this.socket = new ReconnectingWebsocket(`${wsUrl}/${endpoint}${query ? '?' + query : ''}`); + this.socket.addEventListener('open', this.onOpen); + this.socket.addEventListener('close', this.onClose); + this.socket.addEventListener('message', this.onMessage); + + // Register this connection for debugging + this.os.registerStreamConnection(this); + } + + /** + * Callback of when open connection + */ + private onOpen() { + this.state = 'connected'; + this.emit('_connected_'); + + this.connectedAt = new Date(); + + // バッファーを処理 + const _buffer = [].concat(this.buffer); // Shallow copy + this.buffer = []; // Clear buffer + _buffer.forEach(data => { + this.send(data); // Resend each buffered messages + + if (this.os.debug) { + this.out++; + this.inout.push({ type: 'out', at: new Date(), data }); + } + }); + } + + /** + * Callback of when close connection + */ + private onClose() { + this.state = 'reconnecting'; + this.emit('_disconnected_'); + } + + /** + * Callback of when received a message from connection + */ + private onMessage(message) { + if (this.isSuspended) return; + + if (this.os.debug) { + this.in++; + this.inout.push({ type: 'in', at: new Date(), data: message.data }); + } + + try { + const msg = JSON.parse(message.data); + if (msg.type) this.emit(msg.type, msg.body); + } catch (e) { + // noop + } + } + + /** + * Send a message to connection + */ + public send(data) { + if (this.isSuspended) return; + + // まだ接続が確立されていなかったらバッファリングして次に接続した時に送信する + if (this.state != 'connected') { + this.buffer.push(data); + return; + } + + if (this.os.debug) { + this.out++; + this.inout.push({ type: 'out', at: new Date(), data }); + } + + this.socket.send(JSON.stringify(data)); + } + + /** + * Close this connection + */ + public close() { + this.os.unregisterStreamConnection(this); + this.socket.removeEventListener('open', this.onOpen); + this.socket.removeEventListener('message', this.onMessage); + } +} diff --git a/src/server/web/app/common/views/components/autocomplete.vue b/src/server/web/app/common/views/components/autocomplete.vue new file mode 100644 index 0000000000..8afa291e3c --- /dev/null +++ b/src/server/web/app/common/views/components/autocomplete.vue @@ -0,0 +1,306 @@ + + + + + diff --git a/src/server/web/app/common/views/components/connect-failed.troubleshooter.vue b/src/server/web/app/common/views/components/connect-failed.troubleshooter.vue new file mode 100644 index 0000000000..cadbd36ba4 --- /dev/null +++ b/src/server/web/app/common/views/components/connect-failed.troubleshooter.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/src/server/web/app/common/views/components/connect-failed.vue b/src/server/web/app/common/views/components/connect-failed.vue new file mode 100644 index 0000000000..185250dbd8 --- /dev/null +++ b/src/server/web/app/common/views/components/connect-failed.vue @@ -0,0 +1,106 @@ + + + + + + diff --git a/src/server/web/app/common/views/components/ellipsis.vue b/src/server/web/app/common/views/components/ellipsis.vue new file mode 100644 index 0000000000..07349902de --- /dev/null +++ b/src/server/web/app/common/views/components/ellipsis.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/server/web/app/common/views/components/file-type-icon.vue b/src/server/web/app/common/views/components/file-type-icon.vue new file mode 100644 index 0000000000..b7e868d1f7 --- /dev/null +++ b/src/server/web/app/common/views/components/file-type-icon.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/server/web/app/common/views/components/forkit.vue b/src/server/web/app/common/views/components/forkit.vue new file mode 100644 index 0000000000..6f334b965a --- /dev/null +++ b/src/server/web/app/common/views/components/forkit.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/server/web/app/common/views/components/index.ts b/src/server/web/app/common/views/components/index.ts new file mode 100644 index 0000000000..b58ba37ecb --- /dev/null +++ b/src/server/web/app/common/views/components/index.ts @@ -0,0 +1,51 @@ +import Vue from 'vue'; + +import signin from './signin.vue'; +import signup from './signup.vue'; +import forkit from './forkit.vue'; +import nav from './nav.vue'; +import postHtml from './post-html'; +import poll from './poll.vue'; +import pollEditor from './poll-editor.vue'; +import reactionIcon from './reaction-icon.vue'; +import reactionsViewer from './reactions-viewer.vue'; +import time from './time.vue'; +import timer from './timer.vue'; +import mediaList from './media-list.vue'; +import uploader from './uploader.vue'; +import specialMessage from './special-message.vue'; +import streamIndicator from './stream-indicator.vue'; +import ellipsis from './ellipsis.vue'; +import messaging from './messaging.vue'; +import messagingRoom from './messaging-room.vue'; +import urlPreview from './url-preview.vue'; +import twitterSetting from './twitter-setting.vue'; +import fileTypeIcon from './file-type-icon.vue'; +import Switch from './switch.vue'; +import Othello from './othello.vue'; +import welcomeTimeline from './welcome-timeline.vue'; + +Vue.component('mk-signin', signin); +Vue.component('mk-signup', signup); +Vue.component('mk-forkit', forkit); +Vue.component('mk-nav', nav); +Vue.component('mk-post-html', postHtml); +Vue.component('mk-poll', poll); +Vue.component('mk-poll-editor', pollEditor); +Vue.component('mk-reaction-icon', reactionIcon); +Vue.component('mk-reactions-viewer', reactionsViewer); +Vue.component('mk-time', time); +Vue.component('mk-timer', timer); +Vue.component('mk-media-list', mediaList); +Vue.component('mk-uploader', uploader); +Vue.component('mk-special-message', specialMessage); +Vue.component('mk-stream-indicator', streamIndicator); +Vue.component('mk-ellipsis', ellipsis); +Vue.component('mk-messaging', messaging); +Vue.component('mk-messaging-room', messagingRoom); +Vue.component('mk-url-preview', urlPreview); +Vue.component('mk-twitter-setting', twitterSetting); +Vue.component('mk-file-type-icon', fileTypeIcon); +Vue.component('mk-switch', Switch); +Vue.component('mk-othello', Othello); +Vue.component('mk-welcome-timeline', welcomeTimeline); diff --git a/src/server/web/app/common/views/components/media-list.vue b/src/server/web/app/common/views/components/media-list.vue new file mode 100644 index 0000000000..64172ad0b4 --- /dev/null +++ b/src/server/web/app/common/views/components/media-list.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/server/web/app/common/views/components/messaging-room.form.vue b/src/server/web/app/common/views/components/messaging-room.form.vue new file mode 100644 index 0000000000..01886b19c8 --- /dev/null +++ b/src/server/web/app/common/views/components/messaging-room.form.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/src/server/web/app/common/views/components/messaging-room.message.vue b/src/server/web/app/common/views/components/messaging-room.message.vue new file mode 100644 index 0000000000..5f2eb1ba86 --- /dev/null +++ b/src/server/web/app/common/views/components/messaging-room.message.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/src/server/web/app/common/views/components/messaging-room.vue b/src/server/web/app/common/views/components/messaging-room.vue new file mode 100644 index 0000000000..6ff808b617 --- /dev/null +++ b/src/server/web/app/common/views/components/messaging-room.vue @@ -0,0 +1,377 @@ + + + + + diff --git a/src/server/web/app/common/views/components/messaging.vue b/src/server/web/app/common/views/components/messaging.vue new file mode 100644 index 0000000000..88574b94d1 --- /dev/null +++ b/src/server/web/app/common/views/components/messaging.vue @@ -0,0 +1,463 @@ + + + + + diff --git a/src/server/web/app/common/views/components/nav.vue b/src/server/web/app/common/views/components/nav.vue new file mode 100644 index 0000000000..8ce75d3529 --- /dev/null +++ b/src/server/web/app/common/views/components/nav.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/server/web/app/common/views/components/othello.game.vue b/src/server/web/app/common/views/components/othello.game.vue new file mode 100644 index 0000000000..414d819a55 --- /dev/null +++ b/src/server/web/app/common/views/components/othello.game.vue @@ -0,0 +1,324 @@ + + + + + diff --git a/src/server/web/app/common/views/components/othello.gameroom.vue b/src/server/web/app/common/views/components/othello.gameroom.vue new file mode 100644 index 0000000000..38a25f6686 --- /dev/null +++ b/src/server/web/app/common/views/components/othello.gameroom.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/server/web/app/common/views/components/othello.room.vue b/src/server/web/app/common/views/components/othello.room.vue new file mode 100644 index 0000000000..3965414836 --- /dev/null +++ b/src/server/web/app/common/views/components/othello.room.vue @@ -0,0 +1,297 @@ + + + + + + + + + diff --git a/src/server/web/app/common/views/components/othello.vue b/src/server/web/app/common/views/components/othello.vue new file mode 100644 index 0000000000..d650322341 --- /dev/null +++ b/src/server/web/app/common/views/components/othello.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/src/server/web/app/common/views/components/poll-editor.vue b/src/server/web/app/common/views/components/poll-editor.vue new file mode 100644 index 0000000000..47d901d7b1 --- /dev/null +++ b/src/server/web/app/common/views/components/poll-editor.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/server/web/app/common/views/components/poll.vue b/src/server/web/app/common/views/components/poll.vue new file mode 100644 index 0000000000..8156c8bc58 --- /dev/null +++ b/src/server/web/app/common/views/components/poll.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/server/web/app/common/views/components/post-html.ts b/src/server/web/app/common/views/components/post-html.ts new file mode 100644 index 0000000000..98da86617d --- /dev/null +++ b/src/server/web/app/common/views/components/post-html.ts @@ -0,0 +1,137 @@ +import Vue from 'vue'; +import * as emojilib from 'emojilib'; +import getAcct from '../../../../../common/user/get-acct'; +import { url } from '../../../config'; +import MkUrl from './url.vue'; + +const flatten = list => list.reduce( + (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [] +); + +export default Vue.component('mk-post-html', { + props: { + ast: { + type: Array, + required: true + }, + shouldBreak: { + type: Boolean, + default: true + }, + i: { + type: Object, + default: null + } + }, + render(createElement) { + const els = flatten((this as any).ast.map(token => { + switch (token.type) { + case 'text': + const text = token.content.replace(/(\r\n|\n|\r)/g, '\n'); + + if ((this as any).shouldBreak) { + const x = text.split('\n') + .map(t => t == '' ? [createElement('br')] : [createElement('span', t), createElement('br')]); + x[x.length - 1].pop(); + return x; + } else { + return createElement('span', text.replace(/\n/g, ' ')); + } + + case 'bold': + return createElement('strong', token.bold); + + case 'url': + return createElement(MkUrl, { + props: { + url: token.content, + target: '_blank' + } + }); + + case 'link': + return createElement('a', { + attrs: { + class: 'link', + href: token.url, + target: '_blank', + title: token.url + } + }, token.title); + + case 'mention': + return (createElement as any)('a', { + attrs: { + href: `${url}/@${getAcct(token)}`, + target: '_blank', + dataIsMe: (this as any).i && getAcct((this as any).i) == getAcct(token) + }, + directives: [{ + name: 'user-preview', + value: token.content + }] + }, token.content); + + case 'hashtag': + return createElement('a', { + attrs: { + href: `${url}/search?q=${token.content}`, + target: '_blank' + } + }, token.content); + + case 'code': + return createElement('pre', [ + createElement('code', { + domProps: { + innerHTML: token.html + } + }) + ]); + + case 'inline-code': + return createElement('code', token.html); + + case 'quote': + const text2 = token.quote.replace(/(\r\n|\n|\r)/g, '\n'); + + if ((this as any).shouldBreak) { + const x = text2.split('\n') + .map(t => [createElement('span', t), createElement('br')]); + x[x.length - 1].pop(); + return createElement('div', { + attrs: { + class: 'quote' + } + }, x); + } else { + return createElement('span', { + attrs: { + class: 'quote' + } + }, text2.replace(/\n/g, ' ')); + } + + case 'emoji': + const emoji = emojilib.lib[token.emoji]; + return createElement('span', emoji ? emoji.char : token.content); + + default: + console.log('unknown ast type:', token.type); + } + })); + + const _els = []; + els.forEach((el, i) => { + if (el.tag == 'br') { + if (els[i - 1].tag != 'div') { + _els.push(el); + } + } else { + _els.push(el); + } + }); + + return createElement('span', _els); + } +}); diff --git a/src/server/web/app/common/views/components/post-menu.vue b/src/server/web/app/common/views/components/post-menu.vue new file mode 100644 index 0000000000..a53680e55a --- /dev/null +++ b/src/server/web/app/common/views/components/post-menu.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/server/web/app/common/views/components/reaction-icon.vue b/src/server/web/app/common/views/components/reaction-icon.vue new file mode 100644 index 0000000000..7d24f4f9e9 --- /dev/null +++ b/src/server/web/app/common/views/components/reaction-icon.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/src/server/web/app/common/views/components/reaction-picker.vue b/src/server/web/app/common/views/components/reaction-picker.vue new file mode 100644 index 0000000000..df8100f2fc --- /dev/null +++ b/src/server/web/app/common/views/components/reaction-picker.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/server/web/app/common/views/components/reactions-viewer.vue b/src/server/web/app/common/views/components/reactions-viewer.vue new file mode 100644 index 0000000000..f6a27d9139 --- /dev/null +++ b/src/server/web/app/common/views/components/reactions-viewer.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/src/server/web/app/common/views/components/signin.vue b/src/server/web/app/common/views/components/signin.vue new file mode 100644 index 0000000000..2434684085 --- /dev/null +++ b/src/server/web/app/common/views/components/signin.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/server/web/app/common/views/components/signup.vue b/src/server/web/app/common/views/components/signup.vue new file mode 100644 index 0000000000..c2e78aa8a3 --- /dev/null +++ b/src/server/web/app/common/views/components/signup.vue @@ -0,0 +1,287 @@ + + + + + diff --git a/src/server/web/app/common/views/components/special-message.vue b/src/server/web/app/common/views/components/special-message.vue new file mode 100644 index 0000000000..2fd4d6515e --- /dev/null +++ b/src/server/web/app/common/views/components/special-message.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/server/web/app/common/views/components/stream-indicator.vue b/src/server/web/app/common/views/components/stream-indicator.vue new file mode 100644 index 0000000000..1f18fa76ed --- /dev/null +++ b/src/server/web/app/common/views/components/stream-indicator.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/server/web/app/common/views/components/switch.vue b/src/server/web/app/common/views/components/switch.vue new file mode 100644 index 0000000000..19a4adc3de --- /dev/null +++ b/src/server/web/app/common/views/components/switch.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/server/web/app/common/views/components/time.vue b/src/server/web/app/common/views/components/time.vue new file mode 100644 index 0000000000..6e0d2b0dcb --- /dev/null +++ b/src/server/web/app/common/views/components/time.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/server/web/app/common/views/components/timer.vue b/src/server/web/app/common/views/components/timer.vue new file mode 100644 index 0000000000..a3c4f01b77 --- /dev/null +++ b/src/server/web/app/common/views/components/timer.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/server/web/app/common/views/components/twitter-setting.vue b/src/server/web/app/common/views/components/twitter-setting.vue new file mode 100644 index 0000000000..15968d20a6 --- /dev/null +++ b/src/server/web/app/common/views/components/twitter-setting.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/server/web/app/common/views/components/uploader.vue b/src/server/web/app/common/views/components/uploader.vue new file mode 100644 index 0000000000..73006b16e9 --- /dev/null +++ b/src/server/web/app/common/views/components/uploader.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/server/web/app/common/views/components/url-preview.vue b/src/server/web/app/common/views/components/url-preview.vue new file mode 100644 index 0000000000..e91e510550 --- /dev/null +++ b/src/server/web/app/common/views/components/url-preview.vue @@ -0,0 +1,142 @@ +