Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Sharkey
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dima Krasner
Sharkey
Commits
e0aba492
Commit
e0aba492
authored
7 years ago
by
こぴなたみぽ
Browse files
Options
Downloads
Patches
Plain Diff
wip
parent
7b733143
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/web/app/desktop/-tags/post-detail.tag
+0
-328
0 additions, 328 deletions
src/web/app/desktop/-tags/post-detail.tag
src/web/app/desktop/views/components/post-detail.vue
+313
-0
313 additions, 0 deletions
src/web/app/desktop/views/components/post-detail.vue
with
313 additions
and
328 deletions
src/web/app/desktop/-tags/post-detail.tag
deleted
100644 → 0
+
0
−
328
View file @
7b733143
<mk-post-detail title={ title }>
<div class="main">
<button class="read-more" v-if="p.reply && p.reply.reply_id && context == null" title="会話をもっと読み込む" @click="loadContext" disabled={ contextFetching }>
<template v-if="!contextFetching">%fa:ellipsis-v%</template>
<template v-if="contextFetching">%fa:spinner .pulse%</template>
</button>
<div class="context">
<template each={ post in context }>
<mk-post-detail-sub post={ post }/>
</template>
</div>
<div class="reply-to" v-if="p.reply">
<mk-post-detail-sub post={ p.reply }/>
</div>
<div class="repost" v-if="isRepost">
<p>
<a class="avatar-anchor" href={ '/' + post.user.username } data-user-preview={ post.user_id }>
<img class="avatar" src={ post.user.avatar_url + '?thumbnail&size=32' } alt="avatar"/>
</a>
%fa:retweet%<a class="name" href={ '/' + post.user.username }>
{ post.user.name }
</a>
がRepost
</p>
</div>
<article>
<a class="avatar-anchor" href={ '/' + p.user.username }>
<img class="avatar" src={ p.user.avatar_url + '?thumbnail&size=64' } alt="avatar" data-user-preview={ p.user.id }/>
</a>
<header>
<a class="name" href={ '/' + p.user.username } data-user-preview={ p.user.id }>{ p.user.name }</a>
<span class="username">@{ p.user.username }</span>
<a class="time" href={ '/' + p.user.username + '/' + p.id }>
<mk-time time={ p.created_at }/>
</a>
</header>
<div class="body">
<div class="text" ref="text"></div>
<div class="media" v-if="p.media">
<mk-images images={ p.media }/>
</div>
<mk-poll v-if="p.poll" post={ p }/>
</div>
<footer>
<mk-reactions-viewer post={ p }/>
<button @click="reply" title="返信">
%fa:reply%<p class="count" v-if="p.replies_count > 0">{ p.replies_count }</p>
</button>
<button @click="repost" title="Repost">
%fa:retweet%<p class="count" v-if="p.repost_count > 0">{ p.repost_count }</p>
</button>
<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="リアクション">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{ p.reactions_count }</p>
</button>
<button @click="menu" ref="menuButton">
%fa:ellipsis-h%
</button>
</footer>
</article>
<div class="replies" v-if="!compact">
<template each={ post in replies }>
<mk-post-detail-sub post={ post }/>
</template>
</div>
</div>
<style lang="stylus" scoped>
:scope
display block
margin 0
padding 0
overflow hidden
text-align left
background #fff
border solid 1px rgba(0, 0, 0, 0.1)
border-radius 8px
> .main
> .read-more
display block
margin 0
padding 10px 0
width 100%
font-size 1em
text-align center
color #999
cursor pointer
background #fafafa
outline none
border none
border-bottom solid 1px #eef0f2
border-radius 6px 6px 0 0
&:hover
background #f6f6f6
&:active
background #f0f0f0
&:disabled
color #ccc
> .context
> *
border-bottom 1px solid #eef0f2
> .repost
color #9dbb00
background linear-gradient(to bottom, #edfde2 0%, #fff 100%)
> p
margin 0
padding 16px 32px
.avatar-anchor
display inline-block
.avatar
vertical-align bottom
min-width 28px
min-height 28px
max-width 28px
max-height 28px
margin 0 8px 0 0
border-radius 6px
[data-fa]
margin-right 4px
.name
font-weight bold
& + article
padding-top 8px
> .reply-to
border-bottom 1px solid #eef0f2
> article
padding 28px 32px 18px 32px
&:after
content ""
display block
clear both
&:hover
> .main > footer > button
color #888
> .avatar-anchor
display block
width 60px
height 60px
> .avatar
display block
width 60px
height 60px
margin 0
border-radius 8px
vertical-align bottom
> header
position absolute
top 28px
left 108px
width calc(100% - 108px)
> .name
display inline-block
margin 0
line-height 24px
color #777
font-size 18px
font-weight 700
text-align left
text-decoration none
&:hover
text-decoration underline
> .username
display block
text-align left
margin 0
color #ccc
> .time
position absolute
top 0
right 32px
font-size 1em
color #c0c0c0
> .body
padding 8px 0
> .text
cursor default
display block
margin 0
padding 0
overflow-wrap break-word
font-size 1.5em
color #717171
> mk-url-preview
margin-top 8px
> footer
font-size 1.2em
> button
margin 0 28px 0 0
padding 8px
background transparent
border none
font-size 1em
color #ddd
cursor pointer
&:hover
color #666
> .count
display inline
margin 0 0 0 8px
color #999
&.reacted
color $theme-color
> .replies
> *
border-top 1px solid #eef0f2
</style>
<script lang="typescript">
import compile from '../../common/scripts/text-compiler';
import dateStringify from '../../common/scripts/date-stringify';
this.mixin('api');
this.mixin('user-preview');
this.compact = this.opts.compact;
this.contextFetching = false;
this.context = null;
this.post = this.opts.post;
this.isRepost = this.post.repost != null;
this.p = this.isRepost ? this.post.repost : this.post;
this.p.reactions_count = this.p.reaction_counts ? Object.keys(this.p.reaction_counts).map(key => this.p.reaction_counts[key]).reduce((a, b) => a + b) : 0;
this.title = dateStringify(this.p.created_at);
this.on('mount', () => {
if (this.p.text) {
const tokens = this.p.ast;
this.$refs.text.innerHTML = compile(tokens);
Array.from(this.$refs.text.children).forEach(e => {
if (e.tagName == 'MK-URL') riot.mount(e);
});
// URLをプレビュー
tokens
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
.map(t => {
riot.mount(this.$refs.text.appendChild(document.createElement('mk-url-preview')), {
url: t.url
});
});
}
// Get replies
if (!this.compact) {
this.api('posts/replies', {
post_id: this.p.id,
limit: 8
}).then(replies => {
this.update({
replies: replies
});
});
}
});
this.reply = () => {
riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')), {
reply: this.p
});
};
this.repost = () => {
riot.mount(document.body.appendChild(document.createElement('mk-repost-form-window')), {
post: this.p
});
};
this.react = () => {
riot.mount(document.body.appendChild(document.createElement('mk-reaction-picker')), {
source: this.$refs.reactButton,
post: this.p
});
};
this.menu = () => {
riot.mount(document.body.appendChild(document.createElement('mk-post-menu')), {
source: this.$refs.menuButton,
post: this.p
});
};
this.loadContext = () => {
this.contextFetching = true;
// Fetch context
this.api('posts/context', {
post_id: this.p.reply_id
}).then(context => {
this.update({
contextFetching: false,
context: context.reverse()
});
});
};
</script>
</mk-post-detail>
This diff is collapsed.
Click to expand it.
src/web/app/desktop/views/components/post-detail.vue
0 → 100644
+
313
−
0
View file @
e0aba492
<
template
>
<div
class=
"mk-post-detail"
:title=
"title"
>
<button
class=
"read-more"
v-if=
"p.reply && p.reply.reply_id && context == null"
title=
"会話をもっと読み込む"
@
click=
"loadContext"
disabled=
{ contextFetching }>
<template
v-if=
"!contextFetching"
>
%fa:ellipsis-v%
</
template
>
<
template
v-if=
"contextFetching"
>
%fa:spinner .pulse%
</
template
>
</button>
<div
class=
"context"
>
<
template
each=
{
post
in
context
}
>
<mk-post-detail-sub
post=
{ post }/>
</
template
>
</div>
<div
class=
"reply-to"
v-if=
"p.reply"
>
<mk-post-detail-sub
post=
{
p.reply
}
/>
</div>
<div
class=
"repost"
v-if=
"isRepost"
>
<p>
<a
class=
"avatar-anchor"
href=
{
'/'
+
post.user.username
}
data-user-preview=
{
post.user_id
}
>
<img
class=
"avatar"
src=
{
post.user.avatar_url
+
'?
thumbnail
&
size=
32'
}
alt=
"avatar"
/>
</a>
%fa:retweet%
<a
class=
"name"
href=
{
'/'
+
post.user.username
}
>
{ post.user.name }
</a>
がRepost
</p>
</div>
<article>
<a
class=
"avatar-anchor"
href=
{
'/'
+
p.user.username
}
>
<img
class=
"avatar"
src=
{
p.user.avatar_url
+
'?
thumbnail
&
size=
64'
}
alt=
"avatar"
data-user-preview=
{
p.user.id
}
/>
</a>
<header>
<a
class=
"name"
href=
{
'/'
+
p.user.username
}
data-user-preview=
{
p.user.id
}
>
{ p.user.name }
</a>
<span
class=
"username"
>
@{ p.user.username }
</span>
<a
class=
"time"
href=
{
'/'
+
p.user.username
+
'/'
+
p.id
}
>
<mk-time
time=
{
p.created_at
}
/>
</a>
</header>
<div
class=
"body"
>
<mk-post-html
v-if=
"p.ast"
:ast=
"p.ast"
:i=
"$root.$data.os.i"
/>
<mk-url-preview
v-for=
"url in urls"
:url=
"url"
:key=
"url"
/>
<div
class=
"media"
v-if=
"p.media"
>
<mk-images
images=
{
p.media
}
/>
</div>
<mk-poll
v-if=
"p.poll"
post=
{
p
}
/>
</div>
<footer>
<mk-reactions-viewer
post=
{
p
}
/>
<button
@
click=
"reply"
title=
"返信"
>
%fa:reply%
<p
class=
"count"
v-if=
"p.replies_count > 0"
>
{ p.replies_count }
</p>
</button>
<button
@
click=
"repost"
title=
"Repost"
>
%fa:retweet%
<p
class=
"count"
v-if=
"p.repost_count > 0"
>
{ p.repost_count }
</p>
</button>
<button
:class=
"{ reacted: p.my_reaction != null }"
@
click=
"react"
ref=
"reactButton"
title=
"リアクション"
>
%fa:plus%
<p
class=
"count"
v-if=
"p.reactions_count > 0"
>
{ p.reactions_count }
</p>
</button>
<button
@
click=
"menu"
ref=
"menuButton"
>
%fa:ellipsis-h%
</button>
</footer>
</article>
<div
class=
"replies"
v-if=
"!compact"
>
<
template
each=
{
post
in
replies
}
>
<mk-post-detail-sub
post=
{ post }/>
</
template
>
</div>
</div>
</template>
<
script
lang=
"ts"
>
import
Vue
from
'
vue
'
;
import
dateStringify
from
'
../../common/scripts/date-stringify
'
;
export
default
Vue
.
extend
({
props
:
{
post
:
{
type
:
Object
,
required
:
true
},
compact
:
{
default
:
false
}
},
data
()
{
return
{
context
:
[],
contextFetching
:
false
,
replies
:
[],
};
},
computed
:
{
isRepost
():
boolean
{
return
this
.
post
.
repost
!=
null
;
},
p
():
any
{
return
this
.
isRepost
?
this
.
post
.
repost
:
this
.
post
;
},
reactionsCount
():
number
{
return
this
.
p
.
reaction_counts
?
Object
.
keys
(
this
.
p
.
reaction_counts
)
.
map
(
key
=>
this
.
p
.
reaction_counts
[
key
])
.
reduce
((
a
,
b
)
=>
a
+
b
)
:
0
;
},
title
():
string
{
return
dateStringify
(
this
.
p
.
created_at
);
},
urls
():
string
[]
{
if
(
this
.
p
.
ast
)
{
return
this
.
p
.
ast
.
filter
(
t
=>
(
t
.
type
==
'
url
'
||
t
.
type
==
'
link
'
)
&&
!
t
.
silent
)
.
map
(
t
=>
t
.
url
);
}
else
{
return
null
;
}
}
},
mounted
()
{
// Get replies
if
(
!
this
.
compact
)
{
this
.
$root
.
$data
.
os
.
api
(
'
posts/replies
'
,
{
post_id
:
this
.
p
.
id
,
limit
:
8
}).
then
(
replies
=>
{
this
.
replies
=
replies
;
});
}
},
methods
:
{
fetchContext
()
{
this
.
contextFetching
=
true
;
// Fetch context
this
.
$root
.
$data
.
os
.
api
(
'
posts/context
'
,
{
post_id
:
this
.
p
.
reply_id
}).
then
(
context
=>
{
this
.
contextFetching
=
false
;
this
.
context
=
context
.
reverse
();
});
}
}
});
</
script
>
<
style
lang=
"stylus"
scoped
>
.mk-post-detail
margin 0
padding 0
overflow hidden
text-align left
background #fff
border solid 1px rgba(0, 0, 0, 0.1)
border-radius 8px
> .read-more
display block
margin 0
padding 10px 0
width 100%
font-size 1em
text-align center
color #999
cursor pointer
background #fafafa
outline none
border none
border-bottom solid 1px #eef0f2
border-radius 6px 6px 0 0
&:hover
background #f6f6f6
&:active
background #f0f0f0
&:disabled
color #ccc
> .context
> *
border-bottom 1px solid #eef0f2
> .repost
color #9dbb00
background linear-gradient(to bottom, #edfde2 0%, #fff 100%)
> p
margin 0
padding 16px 32px
.avatar-anchor
display inline-block
.avatar
vertical-align bottom
min-width 28px
min-height 28px
max-width 28px
max-height 28px
margin 0 8px 0 0
border-radius 6px
[data-fa]
margin-right 4px
.name
font-weight bold
& + article
padding-top 8px
> .reply-to
border-bottom 1px solid #eef0f2
> article
padding 28px 32px 18px 32px
&:after
content ""
display block
clear both
&:hover
> .main > footer > button
color #888
> .avatar-anchor
display block
width 60px
height 60px
> .avatar
display block
width 60px
height 60px
margin 0
border-radius 8px
vertical-align bottom
> header
position absolute
top 28px
left 108px
width calc(100% - 108px)
> .name
display inline-block
margin 0
line-height 24px
color #777
font-size 18px
font-weight 700
text-align left
text-decoration none
&:hover
text-decoration underline
> .username
display block
text-align left
margin 0
color #ccc
> .time
position absolute
top 0
right 32px
font-size 1em
color #c0c0c0
> .body
padding 8px 0
> .text
cursor default
display block
margin 0
padding 0
overflow-wrap break-word
font-size 1.5em
color #717171
> mk-url-preview
margin-top 8px
> footer
font-size 1.2em
> button
margin 0 28px 0 0
padding 8px
background transparent
border none
font-size 1em
color #ddd
cursor pointer
&:hover
color #666
> .count
display inline
margin 0 0 0 8px
color #999
&.reacted
color $theme-color
> .replies
> *
border-top 1px solid #eef0f2
</
style
>
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment