Commit ec8cfe66cd3dbfa8ddc119bae4546fb25f8c8fd5
Merge pull request #16 from ticktackim/profile
Profilemix irving authored on 8/16/2017, 6:30:20 AM
GitHub committed on 8/16/2017, 6:30:20 AM
Parent: 38e0417253d2dc77736737889d97f936df7f35a0
Parent: 31dca712149ea746e5ee65adb698bb4ce4a82c4e
Files changed
app/html/link.js | changed |
app/html/link.mcss | changed |
app/html/thread-card.js | changed |
app/html/thread-card.mcss | added |
app/page/home.js | changed |
app/page/home.mcss | changed |
app/page/userShow.js | changed |
app/page/userShow.mcss | added |
styles/global.mcss | changed |
styles/button.mcss | added |
styles/markdown.mcss | added |
translations/sync.js | changed |
app/html/link.js | ||
---|---|---|
@@ -9,9 +9,10 @@ | ||
9 | 9 | |
10 | 10 | exports.create = (api) => { |
11 | 11 | return nest('app.html.link', (location, body) => { |
12 | 12 | return h('Link', { |
13 | - 'ev-click': () => api.history.sync.push(location) | |
13 | + 'ev-click': () => api.history.sync.push(location), | |
14 | + className: typeof body === 'string' ? '-string' : '' | |
14 | 15 | }, body) |
15 | 16 | }) |
16 | 17 | } |
17 | 18 |
app/html/link.mcss | ||
---|---|---|
@@ -1,6 +1,10 @@ | ||
1 | 1 | Link { |
2 | 2 | color: blue |
3 | - :hover { | |
4 | - text-decoration: underline | |
3 | + | |
4 | + -string { | |
5 | + :hover { | |
6 | + text-decoration: underline | |
7 | + } | |
5 | 8 | } |
6 | 9 | } |
10 | + |
app/html/thread-card.js | ||
---|---|---|
@@ -88,9 +88,9 @@ | ||
88 | 88 | const onClick = opts.onClick || function () { api.history.sync.push(thread) } |
89 | 89 | const id = `${thread.key}-${JSON.stringify(opts)}` |
90 | 90 | // id is only here to help morphdom morph accurately |
91 | 91 | |
92 | - return h('div.thread', { 'ev-click': onClick, id }, [ | |
92 | + return h('ThreadCard', { 'ev-click': onClick, id }, [ | |
93 | 93 | h('div.context', threadIcon(thread)), |
94 | 94 | h('div.content', [ |
95 | 95 | subjectEl, |
96 | 96 | replySample ? h('div.reply', [ |
app/html/thread-card.mcss | ||
---|---|---|
@@ -1,0 +1,42 @@ | ||
1 | +ThreadCard { | |
2 | + display: flex | |
3 | + align-items: center | |
4 | + | |
5 | + margin-bottom: .5rem | |
6 | + | |
7 | + div.context { | |
8 | + display: flex | |
9 | + margin-right: 1rem | |
10 | + | |
11 | + img { | |
12 | + $smallAvatar | |
13 | + margin-right: .5rem | |
14 | + } | |
15 | + } | |
16 | + | |
17 | + div.content { | |
18 | + flex-grow: 1 | |
19 | + background: #fff | |
20 | + padding: 1rem | |
21 | + border: 1px solid #ddd | |
22 | + border-radius: 2px | |
23 | + | |
24 | + div.subject { | |
25 | + font-size: 1.2rem | |
26 | + margin-bottom: .3rem | |
27 | + | |
28 | + $largeMarkdown | |
29 | + } | |
30 | + div.reply { | |
31 | + display: flex | |
32 | + color: #444 | |
33 | + | |
34 | + div.replySymbol { | |
35 | + margin-left: .7rem | |
36 | + margin-right: .3rem | |
37 | + } | |
38 | + | |
39 | + $smallMarkdown | |
40 | + } | |
41 | + } | |
42 | +} |
app/page/home.js | ||
---|---|---|
@@ -30,9 +30,8 @@ | ||
30 | 30 | return nest('app.page.home', function (location) { |
31 | 31 | // location here can expected to be: { page: 'home' } |
32 | 32 | var strings = api.translations.sync.strings() |
33 | 33 | |
34 | - var container = h('div.container', []) | |
35 | 34 | |
36 | 35 | // function filterForThread (thread) { |
37 | 36 | // if(thread.value.private) |
38 | 37 | // return {private: toRecpGroup(thread)} |
@@ -69,8 +68,9 @@ | ||
69 | 68 | morePlease = true |
70 | 69 | requestIdleCallback(threadsObs.more) |
71 | 70 | } |
72 | 71 | |
72 | + var container = h('div.container', []) | |
73 | 73 | var threadsHtmlObs = More( |
74 | 74 | threadsObsDebounced, |
75 | 75 | function render (threads) { |
76 | 76 | |
@@ -106,21 +106,19 @@ | ||
106 | 106 | h('div.container', [ |
107 | 107 | //private section |
108 | 108 | h('section.updates -directMessage', [ |
109 | 109 | h('div.threads', |
110 | - groupedThreads | |
111 | - .map(function (thread) { | |
110 | + groupedThreads.map(thread => { | |
111 | + const channel = thread.value.content.channel | |
112 | + const onClick = channel | |
113 | + ? (ev) => api.history.sync.push({ channel }) | |
114 | + : null // threadCard will install default onClick | |
112 | 115 | |
113 | - const channel = thread.value.content.channel | |
114 | - const onClick = channel | |
115 | - ? (ev) => api.history.sync.push({ channel }) | |
116 | - : null // threadCard will install default onClick | |
117 | - | |
118 | - return api.app.html.threadCard(thread, { onClick }) | |
116 | + return api.app.html.threadCard(thread, { onClick }) | |
119 | 117 | }) |
120 | 118 | ) |
121 | - ]), | |
122 | - ]) | |
119 | + ]) | |
120 | + ]) | |
123 | 121 | ) |
124 | 122 | |
125 | 123 | return container |
126 | 124 | } |
app/page/home.mcss | ||
---|---|---|
@@ -9,9 +9,9 @@ | ||
9 | 9 | -directMessage { |
10 | 10 | $homePageSection |
11 | 11 | |
12 | 12 | div.threads { |
13 | - div.thread { | |
13 | + div.ThreadCard { | |
14 | 14 | div.content { |
15 | 15 | div.subject { |
16 | 16 | display: flex |
17 | 17 | |
@@ -33,9 +33,9 @@ | ||
33 | 33 | -channel { |
34 | 34 | $homePageSection |
35 | 35 | |
36 | 36 | div.threads { |
37 | - div.thread { | |
37 | + div.ThreadCard { | |
38 | 38 | div.context { |
39 | 39 | background: #fff |
40 | 40 | min-width: 8rem |
41 | 41 | padding: .1rem .3rem |
@@ -73,48 +73,7 @@ | ||
73 | 73 | margin-bottom: .4rem |
74 | 74 | } |
75 | 75 | |
76 | 76 | div.threads { |
77 | - div.thread { | |
78 | - display: flex | |
79 | - align-items: center | |
80 | - | |
81 | - margin-bottom: .5rem | |
82 | - | |
83 | - div.context { | |
84 | - display: flex | |
85 | - margin-right: 1rem | |
86 | - | |
87 | - img { | |
88 | - $smallAvatar | |
89 | - margin-right: .5rem | |
90 | - } | |
91 | - } | |
92 | - | |
93 | - div.content { | |
94 | - flex-grow: 1 | |
95 | - background: #fff | |
96 | - padding: 1rem | |
97 | - border: 1px solid #ddd | |
98 | - border-radius: 2px | |
99 | - | |
100 | - div.subject { | |
101 | - font-size: 1.2rem | |
102 | - margin-bottom: .3rem | |
103 | - | |
104 | - $largeMarkdown | |
105 | - } | |
106 | - div.reply { | |
107 | - display: flex | |
108 | - color: #444 | |
109 | - | |
110 | - div.replySymbol { | |
111 | - margin-left: .7rem | |
112 | - margin-right: .3rem | |
113 | - } | |
114 | - | |
115 | - $smallMarkdown | |
116 | - } | |
117 | - } | |
118 | - } | |
77 | + div.ThreadCard {} | |
119 | 78 | } |
120 | 79 | } |
app/page/userShow.js | ||
---|---|---|
@@ -1,36 +1,97 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const { h } = require('mutant') | |
2 | +const { h, Array: MutantArray, computed, when, map } = require('mutant') | |
3 | +const pull = require('pull-stream') | |
4 | +const get = require('lodash/get') | |
3 | 5 | |
4 | 6 | exports.gives = nest('app.page.userShow') |
5 | 7 | |
6 | 8 | exports.needs = nest({ |
7 | 9 | 'app.html.link': 'first', |
8 | 10 | 'app.html.nav': 'first', |
11 | + 'app.html.threadCard': 'first', | |
9 | 12 | 'about.html.image': 'first', |
10 | 13 | 'about.obs.name': 'first', |
14 | + 'contact.async.follow': 'first', | |
15 | + 'contact.async.unfollow': 'first', | |
16 | + 'contact.obs.followers': 'first', | |
17 | + 'feed.pull.private': 'first', | |
18 | + 'feed.pull.rollup': 'first', | |
11 | 19 | 'keys.sync.id': 'first', |
20 | + 'state.obs.threads': 'first', | |
21 | + 'translations.sync.strings': 'first', | |
12 | 22 | }) |
13 | 23 | |
14 | 24 | exports.create = (api) => { |
15 | 25 | return nest('app.page.userShow', userShow) |
16 | 26 | |
17 | 27 | function userShow (location) { |
18 | 28 | |
19 | 29 | const { feed } = location |
20 | - const Link = api.app.html.link | |
21 | 30 | const myId = api.keys.sync.id() |
22 | 31 | |
32 | + const strings = api.translations.sync.strings() | |
33 | + | |
34 | + const { followers } = api.contact.obs | |
35 | + | |
36 | + const youFollowThem = computed(followers(feed), followers => followers.has(myId)) | |
37 | + const theyFollowYou = computed(followers(myId), followers => followers.has(feed)) | |
38 | + const youAreFriends = computed([youFollowThem, theyFollowYou], (a, b) => a && b) | |
39 | + | |
40 | + const ourRelationship = computed( | |
41 | + [youAreFriends, youFollowThem, theyFollowYou], | |
42 | + (youAreFriends, youFollowThem, theyFollowYou) => { | |
43 | + if (youAreFriends) return strings.userShow.state.friends | |
44 | + if (theyFollowYou) return strings.userShow.state.theyFollow | |
45 | + if (youFollowThem) return strings.userShow.state.youFollow | |
46 | + } | |
47 | + ) | |
48 | + const { unfollow, follow } = api.contact.async | |
49 | + const followButton = when(followers(myId).sync, | |
50 | + when(youFollowThem, | |
51 | + h('Button -subtle', { 'ev-click': () => unfollow(feed) }, strings.userShow.action.unfollow), | |
52 | + h('Button -primary', { 'ev-click': () => follow(feed) }, strings.userShow.action.follow) | |
53 | + ), | |
54 | + h('Button', { disabled: 'disabled' }, strings.loading ) | |
55 | + ) | |
56 | + | |
57 | + | |
58 | + const threads = MutantArray() | |
59 | + pull( | |
60 | + // next(api.feed.pull.private, {reverse: true, limit: 100, live: false}, ['value', 'timestamp']), | |
61 | + // api.feed.pull.private({reverse: true, limit: 100, live: false}), | |
62 | + api.feed.pull.private({reverse: true, live: false}), | |
63 | + pull.filter(msg => { | |
64 | + const recps = get(msg, 'value.content.recps') | |
65 | + if (!recps) return | |
66 | + | |
67 | + return recps | |
68 | + .map(r => typeof r === 'object' ? r.link : r) | |
69 | + .includes(feed) | |
70 | + }), | |
71 | + api.feed.pull.rollup(), | |
72 | + pull.drain(threads.push) | |
73 | + // Scroller(container, content, render, false, false) | |
74 | + ) | |
75 | + | |
76 | + const Link = api.app.html.link | |
77 | + | |
23 | 78 | return h('Page -userShow', [ |
79 | + api.app.html.nav(), | |
24 | 80 | h('h1', api.about.obs.name(feed)), |
25 | - api.app.html.nav(), | |
26 | - api.about.html.image(feed), | |
27 | - h('div', 'follow button'), | |
28 | - h('div', 'friends in common'), | |
29 | - feed !== myId | |
30 | - ? Link({ page: 'threadNew', feed }, 'New Thread') | |
31 | - : '', | |
32 | - h('div', 'conversations you\'ve had with dominic'), | |
33 | - h('div', 'groups dominic is in'), | |
81 | + h('div.container', [ | |
82 | + api.about.html.image(feed), | |
83 | + feed !== myId | |
84 | + ? h('div.friendship', [ | |
85 | + h('div.state', ourRelationship), | |
86 | + followButton | |
87 | + ]) : '', | |
88 | + h('div', '...friends in common'), | |
89 | + h('div', '...groups this person is in'), | |
90 | + feed !== myId | |
91 | + ? Link({ page: 'threadNew', feed }, h('Button -primary', strings.userShow.action.directMessage)) | |
92 | + : '', | |
93 | + h('div.threads', map(threads, api.app.html.threadCard)) | |
94 | + ]) | |
34 | 95 | ]) |
35 | 96 | } |
36 | 97 | } |
app/page/userShow.mcss | ||
---|---|---|
@@ -1,0 +1,17 @@ | ||
1 | +Page -userShow { | |
2 | + div.container { | |
3 | + | |
4 | + div.friendship { | |
5 | + display: flex | |
6 | + align-items: center | |
7 | + | |
8 | + margin-bottom: 1rem | |
9 | + | |
10 | + div.state { flex-basis: 12rem } | |
11 | + div.Button {} | |
12 | + } | |
13 | + | |
14 | + | |
15 | + } | |
16 | +} | |
17 | + |
styles/global.mcss | ||
---|---|---|
@@ -17,16 +17,7 @@ | ||
17 | 17 | img { |
18 | 18 | max-width: 100% |
19 | 19 | } |
20 | 20 | |
21 | -Markdown { | |
22 | - word-break: break-word | |
23 | - | |
24 | - (img) { | |
25 | - margin: .5rem 0 | |
26 | - border-radius: .5rem | |
27 | - } | |
28 | -} | |
29 | - | |
30 | 21 | button { |
31 | 22 | width: 100% |
32 | 23 | } |
styles/button.mcss | ||
---|---|---|
@@ -1,0 +1,27 @@ | ||
1 | +Button { | |
2 | + font-family: arial | |
3 | + text-align: center | |
4 | + | |
5 | + cursor: pointer | |
6 | + | |
7 | + padding: .2rem 2rem | |
8 | + min-width: 4rem | |
9 | + border: 1px #b9b9b9 solid | |
10 | + | |
11 | + -subtle { | |
12 | + color: #b9b9b9 | |
13 | + :hover { | |
14 | + color: #222 | |
15 | + } | |
16 | + } | |
17 | + -primary { | |
18 | + $primaryColor | |
19 | + | |
20 | + :hover { | |
21 | + opacity: .9 | |
22 | + } | |
23 | + | |
24 | + border: none | |
25 | + } | |
26 | +} | |
27 | + |
styles/markdown.mcss | ||
---|---|---|
@@ -1,0 +1,10 @@ | ||
1 | +Markdown { | |
2 | + word-break: break-word | |
3 | + | |
4 | + (img) { | |
5 | + margin: .5rem 0 | |
6 | + border-radius: .5rem | |
7 | + } | |
8 | +} | |
9 | + | |
10 | + |
translations/sync.js | ||
---|---|---|
@@ -1,13 +1,28 @@ | ||
1 | +const nest = require('depnest') | |
1 | 2 | |
2 | -exports.gives = {translations: {sync: {strings: true}}} | |
3 | +exports.gives = nest('translations.sync.strings') | |
3 | 4 | |
4 | -exports.create = function () { | |
5 | - return {translations: {sync: {strings: function () { | |
6 | - return { | |
7 | - showMore: "Show More", | |
8 | - channels: "Channels", | |
9 | - directMessages: "Direct Messages", | |
10 | - replySymbol: "> " | |
5 | +exports.create = (api) => { | |
6 | + return nest('translations.sync.strings', () => en) | |
7 | +} | |
8 | + | |
9 | +const en = { | |
10 | + loading: 'Loading...', | |
11 | + showMore: 'Show More', | |
12 | + channels: 'Channels', | |
13 | + directMessages: 'Direct Messages', | |
14 | + replySymbol: '> ', | |
15 | + userShow: { | |
16 | + action: { | |
17 | + follow: 'Follow', | |
18 | + unfollow: 'Unfollow', | |
19 | + directMessage: 'New Direct Message' | |
20 | + }, | |
21 | + state: { | |
22 | + friends: 'You are friends', | |
23 | + youFollow: 'You follow them', | |
24 | + theyFollow: 'They follow you' | |
11 | 25 | } |
12 | - }}}} | |
26 | + } | |
13 | 27 | } |
28 | + |
Built with git-ssb-web