Initial commit 🍀

This commit is contained in:
syuilo 2016-12-29 07:49:51 +09:00
commit b3f42e62af
405 changed files with 31017 additions and 0 deletions

View file

@ -0,0 +1,108 @@
# Autocomplete
#================================
get-caret-coordinates = require 'textarea-caret-position'
riot = require 'riot'
# オートコンプリートを管理するクラスです。
class Autocomplete
@textarea = null
@suggestion = null
# 対象のテキストエリアを与えてインスタンスを初期化します。
(textarea) ~>
@textarea = textarea
# このインスタンスにあるテキストエリアの入力のキャプチャを開始します。
attach: ~>
@textarea.add-event-listener \input @on-input
# このインスタンスにあるテキストエリアの入力のキャプチャを解除します。
detach: ~>
@textarea.remove-event-listener \input @on-input
@close!
# テキスト入力時
on-input: ~>
@close!
caret = @textarea.selection-start
text = @textarea.value.substr 0 caret
mention-index = text.last-index-of \@
if mention-index == -1
return
username = text.substr mention-index + 1
if not username.match /^[a-zA-Z0-9-]+$/
return
@open \user username
# サジェストを提示します。
open: (type, q) ~>
# 既に開いているサジェストは閉じる
@close!
# サジェスト要素作成
suggestion = document.create-element \mk-autocomplete-suggestion
# ~ サジェストを表示すべき位置を計算 ~
caret-position = get-caret-coordinates @textarea, @textarea.selection-start
rect = @textarea.get-bounding-client-rect!
x = rect.left + window.page-x-offset + caret-position.left
y = rect.top + window.page-y-offset + caret-position.top
suggestion.style.left = x + \px
suggestion.style.top = y + \px
# 要素追加
el = document.body.append-child suggestion
# マウント
mounted = riot.mount el, do
textarea: @textarea
complete: @complete
close: @close
type: type
q: q
@suggestion = mounted.0
# サジェストを閉じます。
close: ~>
if !@suggestion?
return
@suggestion.unmount!
@suggestion = null
@textarea.focus!
# オートコンプリートする
complete: (user) ~>
@close!
value = user.username
caret = @textarea.selection-start
source = @textarea.value
before = source.substr 0 caret
trimed-before = before.substring 0 before.last-index-of \@
after = source.substr caret
# 結果を挿入する
@textarea.value = trimed-before + \@ + value + ' ' + after
# キャレットを戻す
@textarea.focus!
pos = caret + value.length
@textarea.set-selection-range pos, pos
module.exports = Autocomplete

View file

@ -0,0 +1,17 @@
# Dialog
#================================
riot = require 'riot'
module.exports = (title, text, buttons, can-through, on-through) ~>
dialog = document.body.append-child document.create-element \mk-dialog
controller = riot.observable!
riot.mount dialog, do
controller: controller
title: title
text: text
buttons: buttons
can-through: can-through
on-through: on-through
controller.trigger \open
return controller

View file

@ -0,0 +1,56 @@
class Follower
(el) ->
@follower = el
@last-scroll-top = window.scroll-y
@initial-follower-top = @follower.get-bounding-client-rect!.top
@page-top = 48
follow: ->
window-height = window.inner-height
follower-height = @follower.offset-height
scroll-top = window.scroll-y
scroll-bottom = scroll-top + window-height
follower-top = @follower.get-bounding-client-rect!.top + scroll-top
follower-bottom = follower-top + follower-height
height-delta = Math.abs window-height - follower-height
scroll-delta = @last-scroll-top - scroll-top
is-scrolling-down = (scroll-top > @last-scroll-top)
is-window-larger = (window-height > follower-height)
console.log @initial-follower-top
if (is-window-larger && scroll-top > @initial-follower-top) || (!is-window-larger && scroll-top > @initial-follower-top + height-delta)
@follower.class-list.add \fixed
else if !is-scrolling-down && scroll-top + @page-top <= @initial-follower-top
@follower.class-list.remove \fixed
@follower.style.top = 0
return
drag-bottom-down = (follower-bottom <= scroll-bottom && is-scrolling-down)
drag-top-up = (follower-top >= scroll-top + @page-top && !is-scrolling-down)
if drag-bottom-down
console.log \down
@follower.style.top = if is-window-larger then 0 else -height-delta + \px
else if drag-top-up
console.log \up
@follower.style.top = @page-top + \px
else if @follower.class-list.contains \fixed
console.log \-
current-top = parse-int @follower.style.top, 10
min-top = -height-delta
scrolled-top = current-top + scroll-delta
is-page-at-bottom = (scroll-top + window-height >= document.body.offset-height)
new-top = if is-page-at-bottom then min-top else scrolled-top
@follower.style.top = new-top + \px
@last-scroll-top = scroll-top
module.exports = Follower

View file

@ -0,0 +1,19 @@
# FUCK AD BLOCK
#================================
require 'fuck-adblock'
dialog = require './dialog.ls'
module.exports = ~>
if fuck-ad-block == undefined
ad-block-detected!
else
fuck-ad-block.on-detected ad-block-detected
function ad-block-detected
dialog do
'<i class="fa fa-exclamation-triangle"></i>広告ブロッカーを無効にしてください'
'<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。'
[
text: \OK
]

View file

@ -0,0 +1,13 @@
# Input Dialog
#================================
riot = require 'riot'
module.exports = (title, placeholder, default-value, on-ok, on-cancel) ~>
dialog = document.body.append-child document.create-element \mk-input-dialog
riot.mount dialog, do
title: title
placeholder: placeholder
default: default-value
on-ok: on-ok
on-cancel: on-cancel

View file

@ -0,0 +1,6 @@
riot = require \riot
module.exports = (message) ~>
notification = document.body.append-child document.create-element \mk-ui-notification
riot.mount notification, do
message: message

View file

@ -0,0 +1,8 @@
riot = require \riot
function open(name, opts)
window = document.body.append-child document.create-element name
riot.mount window, opts
riot.mixin \open-window do
open-window: open

View file

@ -0,0 +1,38 @@
# Stream
#================================
stream = require '../../common/scripts/stream.ls'
get-post-summary = require '../../common/scripts/get-post-summary.ls'
riot = require \riot
module.exports = (me) ~>
s = stream me
s.event.on \drive_file_created (file) ~>
n = new Notification 'ファイルがアップロードされました' do
body: file.name
icon: file.url + '?thumbnail&size=64'
set-timeout (n.close.bind n), 5000ms
s.event.on \mention (post) ~>
n = new Notification "#{post.user.name}さんから:" do
body: get-post-summary post
icon: post.user.avatar_url + '?thumbnail&size=64'
set-timeout (n.close.bind n), 6000ms
s.event.on \reply (post) ~>
n = new Notification "#{post.user.name}さんから返信:" do
body: get-post-summary post
icon: post.user.avatar_url + '?thumbnail&size=64'
set-timeout (n.close.bind n), 6000ms
s.event.on \quote (post) ~>
n = new Notification "#{post.user.name}さんが引用:" do
body: get-post-summary post
icon: post.user.avatar_url + '?thumbnail&size=64'
set-timeout (n.close.bind n), 6000ms
riot.mixin \stream do
stream: s.event
get-stream-state: s.get-state
stream-state-ev: s.state-ev

View file

@ -0,0 +1,81 @@
# Update Avatar
#================================
riot = require 'riot'
dialog = require './dialog.ls'
api = require '../../common/scripts/api.ls'
module.exports = (I, cb, file = null) ~>
@file-selected = (file) ~>
cropper = document.body.append-child document.create-element \mk-crop-window
cropper = riot.mount cropper, do
file: file
title: 'アバターとして表示する部分を選択'
aspect-ratio: 1 / 1
.0
cropper.on \cropped (blob) ~>
data = new FormData!
data.append \i I.token
data.append \file blob, file.name + '.cropped.png'
api I, \drive/folders/find do
name: 'アイコン'
.then (icon-folder) ~>
if icon-folder.length == 0
api I, \drive/folders/create do
name: 'アイコン'
.then (icon-folder) ~>
@uplaod data, icon-folder
else
@uplaod data, icon-folder.0
cropper.on \skiped ~>
@set file
@uplaod = (data, folder) ~>
progress = document.body.append-child document.create-element \mk-progress-dialog
progress = riot.mount progress, do
title: '新しいアバターをアップロードしています'
.0
if folder?
data.append \folder_id folder.id
xhr = new XMLHttpRequest!
xhr.open \POST CONFIG.api.url + \/drive/files/create true
xhr.onload = (e) ~>
file = JSON.parse e.target.response
progress.close!
@set file
xhr.upload.onprogress = (e) ~>
if e.length-computable
progress.update-progress e.loaded, e.total
xhr.send data
@set = (file) ~>
api I, \i/update do
avatar_id: file.id
.then (i) ~>
dialog do
'<i class="fa fa-info-circle"></i>アバターを更新しました'
'新しいアバターが反映されるまで時間がかかる場合があります。'
[
text: \わかった
]
if cb? then cb i
.catch (err) ~>
console.error err
#@opts.ui.trigger \notification 'Error!'
if file?
@file-selected file
else
browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
browser = riot.mount browser, do
multiple: false
title: '<i class="fa fa-picture-o"></i>アバターにする画像を選択'
.0
browser.one \selected (file) ~>
@file-selected file

View file

@ -0,0 +1,81 @@
# Update Banner
#================================
riot = require 'riot'
dialog = require './dialog.ls'
api = require '../../common/scripts/api.ls'
module.exports = (I, cb, file = null) ~>
@file-selected = (file) ~>
cropper = document.body.append-child document.create-element \mk-crop-window
cropper = riot.mount cropper, do
file: file
title: 'バナーとして表示する部分を選択'
aspect-ratio: 16 / 9
.0
cropper.on \cropped (blob) ~>
data = new FormData!
data.append \i I.token
data.append \file blob, file.name + '.cropped.png'
api I, \drive/folders/find do
name: 'バナー'
.then (banner-folder) ~>
if banner-folder.length == 0
api I, \drive/folders/create do
name: 'バナー'
.then (banner-folder) ~>
@uplaod data, banner-folder
else
@uplaod data, banner-folder.0
cropper.on \skiped ~>
@set file
@uplaod = (data, folder) ~>
progress = document.body.append-child document.create-element \mk-progress-dialog
progress = riot.mount progress, do
title: '新しいバナーをアップロードしています'
.0
if folder?
data.append \folder_id folder.id
xhr = new XMLHttpRequest!
xhr.open \POST CONFIG.api.url + \/drive/files/create true
xhr.onload = (e) ~>
file = JSON.parse e.target.response
progress.close!
@set file
xhr.upload.onprogress = (e) ~>
if e.length-computable
progress.update-progress e.loaded, e.total
xhr.send data
@set = (file) ~>
api I, \i/update do
banner_id: file.id
.then (i) ~>
dialog do
'<i class="fa fa-info-circle"></i>バナーを更新しました'
'新しいバナーが反映されるまで時間がかかる場合があります。'
[
text: \わかりました。
]
if cb? then cb i
.catch (err) ~>
console.error err
#@opts.ui.trigger \notification 'Error!'
if file?
@file-selected file
else
browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
browser = riot.mount browser, do
multiple: false
title: '<i class="fa fa-picture-o"></i>バナーにする画像を選択'
.0
browser.one \selected (file) ~>
@file-selected file

View file

@ -0,0 +1,35 @@
# Update Wallpaper
#================================
riot = require 'riot'
dialog = require './dialog.ls'
api = require '../../common/scripts/api.ls'
module.exports = (I, cb, file = null) ~>
@set = (file) ~>
api I, \i/appdata/set do
data: JSON.stringify do
wallpaper: file.id
.then (i) ~>
dialog do
'<i class="fa fa-info-circle"></i>壁紙を更新しました'
'新しい壁紙が反映されるまで時間がかかる場合があります。'
[
text: \はい
]
if cb? then cb i
.catch (err) ~>
console.error err
#@opts.ui.trigger \notification 'Error!'
if file?
@set file
else
browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
browser = riot.mount browser, do
multiple: false
title: '<i class="fa fa-picture-o"></i>壁紙にする画像を選択'
.0
browser.one \selected (file) ~>
@set file

View file

@ -0,0 +1,74 @@
# User Preview
#================================
riot = require \riot
riot.mixin \user-preview do
init: ->
@on \mount ~>
scan.call @
@on \updated ~>
scan.call @
function scan
elems = @root.query-selector-all '[data-user-preview]:not([data-user-preview-attached])'
elems.for-each attach.bind @
function attach el
el.set-attribute \data-user-preview-attached true
user = el.get-attribute \data-user-preview
tag = null
show-timer = null
hide-timer = null
el.add-event-listener \mouseover ~>
clear-timeout show-timer
clear-timeout hide-timer
show-timer := set-timeout ~>
show!
, 500ms
el.add-event-listener \mouseleave ~>
clear-timeout show-timer
clear-timeout hide-timer
hide-timer := set-timeout ~>
close!
, 500ms
@on \unmount ~>
clear-timeout show-timer
clear-timeout hide-timer
close!
function show
if tag?
return
preview = document.create-element \mk-user-preview
rect = el.get-bounding-client-rect!
x = rect.left + el.offset-width + window.page-x-offset
y = rect.top + window.page-y-offset
preview.style.top = y + \px
preview.style.left = x + \px
preview.add-event-listener \mouseover ~>
clear-timeout hide-timer
preview.add-event-listener \mouseleave ~>
clear-timeout show-timer
hide-timer := set-timeout ~>
close!
, 500ms
tag := riot.mount (document.body.append-child preview), do
user: user
.0
function close
if tag?
tag.close!
tag := null