Commit f279e0482bb337ac884bc177d679b808a5821f23
Merge branch 'master' into blob-blog
Dominic Tarr committed on 12/6/2017, 11:44:35 PMParent: 7cf45e7c039b145503518e3560ac8943fa1e3708
Parent: c89775f18f4db508d01519014235d1e9419af81b
Files changed
about/html/avatar.mcss | changed |
app/html/blogNav.js | changed |
app/html/comments.js | changed |
app/html/comments.mcss | changed |
app/html/context.js | changed |
app/html/thread.js | changed |
app/html/thread.mcss | changed |
app/index.js | changed |
app/page/blogNew.js | changed |
app/page/blogShow.js | changed |
app/page/blogShow.mcss | changed |
app/page/settings.js | changed |
app/page/settings.mcss | changed |
app/page/userEdit.js | changed |
app/page/userEdit.mcss | changed |
app/page/userShow.js | changed |
app/page/userShow.mcss | changed |
app/sync/initialize/suggests.js | changed |
app/sync/initialize/zoomMemory.js | added |
message/html/likes.mcss | changed |
package-lock.json | changed |
package.json | changed |
styles/button.mcss | changed |
styles/global.mcss | changed |
styles/mixins.js | changed |
translations/en.js | changed |
translations/zh.js | changed |
about/html/avatar.mcss | ||
---|---|---|
@@ -14,8 +14,8 @@ | ||
14 | 14 | $circleMedium |
15 | 15 | } |
16 | 16 | |
17 | 17 | -large { |
18 | - $circlelarge | |
18 | + $circleLarge | |
19 | 19 | } |
20 | 20 | } |
21 | 21 |
app/html/blogNav.js | ||
---|---|---|
@@ -5,15 +5,17 @@ | ||
5 | 5 | exports.gives = nest('app.html.blogNav') |
6 | 6 | |
7 | 7 | exports.needs = nest({ |
8 | 8 | 'history.sync.push': 'first', |
9 | + 'history.sync.back': 'first', | |
9 | 10 | 'translations.sync.strings': 'first', |
10 | 11 | }) |
11 | 12 | |
12 | 13 | exports.create = (api) => { |
13 | 14 | return nest('app.html.blogNav', (location) => { |
14 | 15 | const strings = api.translations.sync.strings() |
15 | 16 | const goTo = (loc) => () => api.history.sync.push(loc) |
17 | + const back = () => api.history.sync.back() | |
16 | 18 | |
17 | 19 | if (location.page === 'blogIndex' || location.page === 'blogSearch') { |
18 | 20 | return h('BlogNav', [ |
19 | 21 | h('div.left', [ |
@@ -33,9 +35,9 @@ | ||
33 | 35 | } |
34 | 36 | |
35 | 37 | return h('BlogNav', [ |
36 | 38 | h('div.left', [ |
37 | - h('div.-discovery', { 'ev-click': goTo({ page: 'blogIndex' }) }, [ | |
39 | + h('div.-discovery', { 'ev-click': back }, [ | |
38 | 40 | h('i.fa.fa-chevron-left'), |
39 | 41 | strings.blogIndex.title |
40 | 42 | ]), |
41 | 43 | ]), |
app/html/comments.js | ||
---|---|---|
@@ -39,16 +39,16 @@ | ||
39 | 39 | root, |
40 | 40 | branch, |
41 | 41 | channel |
42 | 42 | } |
43 | - const twoComposers = computed(messages, messages => { | |
44 | - return messages.length > 5 | |
45 | - }) | |
43 | + // const twoComposers = computed(messages, messages => { | |
44 | + // return messages.length > 5 | |
45 | + // }) | |
46 | 46 | const { compose } = api.message.html |
47 | 47 | |
48 | 48 | |
49 | 49 | return h('Comments', [ |
50 | - when(twoComposers, compose({ meta, shrink: true, canAttach: false })), | |
50 | + // when(twoComposers, compose({ meta, shrink: true, canAttach: false })), | |
51 | 51 | map(messagesTree, msg => Comment(msg, root, branch)), |
52 | 52 | compose({ meta, shrink: false, canAttach: false }), |
53 | 53 | ]) |
54 | 54 | } |
app/html/comments.mcss | ||
---|---|---|
@@ -35,9 +35,9 @@ | ||
35 | 35 | div.Timeago {} |
36 | 36 | } |
37 | 37 | |
38 | 38 | section.content { |
39 | - font-size: .9rem | |
39 | + font-size: .95rem | |
40 | 40 | line-height: 1.4 |
41 | 41 | div.Markdown {} |
42 | 42 | } |
43 | 43 | |
@@ -56,17 +56,9 @@ | ||
56 | 56 | margin-right: 1.5rem |
57 | 57 | i.fa {} |
58 | 58 | } |
59 | 59 | |
60 | - div.Likes { | |
61 | - min-width: 2.5rem | |
62 | - | |
63 | - display: flex | |
64 | - align-items: center | |
65 | - | |
66 | - i.fa { margin-right: .3rem } | |
67 | - div.count {} | |
68 | - } | |
60 | + div.Likes { } | |
69 | 61 | } |
70 | 62 | |
71 | 63 | div.Compose { |
72 | 64 | margin: 1rem 0 |
app/html/context.js | ||
---|---|---|
@@ -70,9 +70,9 @@ | ||
70 | 70 | ]) |
71 | 71 | |
72 | 72 | function LevelOneContext () { |
73 | 73 | function isDiscoverContext (loc) { |
74 | - const PAGES_UNDER_DISCOVER = ['blogIndex', 'blogShow'] | |
74 | + const PAGES_UNDER_DISCOVER = ['blogIndex', 'blogShow', 'userShow'] | |
75 | 75 | |
76 | 76 | return PAGES_UNDER_DISCOVER.includes(location.page) |
77 | 77 | || get(location, 'value.private') === undefined |
78 | 78 | } |
@@ -180,8 +180,9 @@ | ||
180 | 180 | function LevelTwoContext () { |
181 | 181 | const { key, value, feed: targetUser, page } = location |
182 | 182 | const root = get(value, 'content.root', key) |
183 | 183 | if (!targetUser) return |
184 | + if (page === 'userShow') return | |
184 | 185 | |
185 | 186 | |
186 | 187 | const prepend = Option({ |
187 | 188 | selected: page === 'threadNew', |
app/html/thread.js | ||
---|---|---|
@@ -9,8 +9,9 @@ | ||
9 | 9 | 'about.html.avatar': 'first', |
10 | 10 | 'feed.obs.thread': 'first', |
11 | 11 | 'keys.sync.id': 'first', |
12 | 12 | 'message.html.markdown': 'first', |
13 | + 'message.html.timeago': 'first', | |
13 | 14 | 'unread.sync.markRead': 'first', |
14 | 15 | 'unread.sync.isUnread': 'first' |
15 | 16 | }) |
16 | 17 | |
@@ -31,18 +32,20 @@ | ||
31 | 32 | h('Avatar -small'), |
32 | 33 | h('div.msgs', map(chunk, msg => { |
33 | 34 | return h('div.msg-row', [ |
34 | 35 | h('div.spacer'), |
35 | - message(msg) | |
36 | + message(msg), | |
37 | + api.message.html.timeago(msg) | |
36 | 38 | ]) |
37 | 39 | })) |
38 | 40 | ]) |
39 | 41 | : h('div.other-chunk', [ |
40 | 42 | when(author, api.about.html.avatar(author()), 'small'), |
41 | 43 | h('div.msgs', map(chunk, msg => { |
42 | 44 | return h('div.msg-row', [ |
43 | 45 | message(msg), |
44 | - h('div.spacer') | |
46 | + h('div.spacer'), | |
47 | + api.message.html.timeago(msg) | |
45 | 48 | ]) |
46 | 49 | })) |
47 | 50 | ]) |
48 | 51 | }) |
app/html/thread.mcss | ||
---|---|---|
@@ -36,9 +36,12 @@ | ||
36 | 36 | |
37 | 37 | -unread { |
38 | 38 | font-weight: bold |
39 | 39 | } |
40 | + } | |
40 | 41 | |
42 | + div.Timeago { | |
43 | + justify-content: flex-start | |
41 | 44 | } |
42 | 45 | } |
43 | 46 | } |
44 | 47 | } |
@@ -55,8 +58,9 @@ | ||
55 | 58 | div.msgs { |
56 | 59 | max-width: 80% |
57 | 60 | div.msg-row { |
58 | 61 | display: flex |
62 | + flex-wrap: wrap | |
59 | 63 | |
60 | 64 | margin-bottom: 3px |
61 | 65 | |
62 | 66 | :first-child { |
@@ -74,10 +78,28 @@ | ||
74 | 78 | } |
75 | 79 | div.spacer { |
76 | 80 | flex-grow: 1 |
77 | 81 | } |
82 | + div.Timeago { | |
83 | + display: none | |
84 | + | |
85 | + flex-basis: 100% | |
86 | + margin: .2rem | |
87 | + | |
88 | + /* display: flex */ | |
89 | + justify-content: flex-end | |
90 | + } | |
78 | 91 | } |
79 | 92 | } |
93 | + | |
94 | + | |
95 | + div.msgs { | |
96 | + div.msg-row { | |
97 | + :last-child { | |
98 | + div.Timeago { | |
99 | + display: flex | |
100 | + } | |
101 | + } | |
102 | + } | |
103 | + } | |
80 | 104 | } |
81 | 105 | |
82 | - | |
83 | - |
app/index.js | ||
---|---|---|
@@ -37,8 +37,9 @@ | ||
37 | 37 | initialize: { |
38 | 38 | clickHandler: require('./sync/initialize/clickHandler'), |
39 | 39 | styles: require('./sync/initialize/styles'), |
40 | 40 | suggests: require('./sync/initialize/suggests'), |
41 | + zoomMemory: require('./sync/initialize/zoomMemory'), | |
41 | 42 | }, |
42 | 43 | } |
43 | 44 | } |
44 | 45 |
app/page/blogNew.js | ||
---|---|---|
@@ -44,9 +44,9 @@ | ||
44 | 44 | cb(null, content) |
45 | 45 | }) |
46 | 46 | } |
47 | 47 | }, |
48 | - (err, msg) => api.history.sync.push(err ? err : msg) | |
48 | + (err, msg) => api.history.sync.push(err ? err : { page: 'blogIndex' }) | |
49 | 49 | ) |
50 | 50 | |
51 | 51 | const channelInput = h('input', { |
52 | 52 | 'ev-input': e => meta.channel.set(e.target.value), |
app/page/blogShow.js | ||
---|---|---|
@@ -13,8 +13,9 @@ | ||
13 | 13 | 'app.html.comments': 'first', |
14 | 14 | 'app.html.context': 'first', |
15 | 15 | 'contact.html.follow': 'first', |
16 | 16 | 'message.html.channel': 'first', |
17 | + 'message.html.likes': 'first', | |
17 | 18 | 'message.html.markdown': 'first', |
18 | 19 | 'message.html.timeago': 'first', |
19 | 20 | 'feed.obs.thread': 'first', |
20 | 21 | |
@@ -50,9 +51,10 @@ | ||
50 | 51 | h('header', [ |
51 | 52 | h('div.blog', [ |
52 | 53 | h('h1', title), |
53 | 54 | timeago(blogMsg), |
54 | - channel(blogMsg) | |
55 | + channel(blogMsg), | |
56 | + api.message.html.likes(blogMsg) | |
55 | 57 | ]), |
56 | 58 | h('div.author', [ |
57 | 59 | h('div.leftCol', api.about.html.avatar(author, 'medium')), |
58 | 60 | h('div.rightCol', [ |
app/page/blogShow.mcss | ||
---|---|---|
@@ -28,8 +28,9 @@ | ||
28 | 28 | div.blog { |
29 | 29 | display: flex |
30 | 30 | flex-wrap: wrap |
31 | 31 | flex-grow: 1 |
32 | + align-items: center | |
32 | 33 | |
33 | 34 | h1 { |
34 | 35 | flex-basis: 100% |
35 | 36 | |
@@ -43,9 +44,13 @@ | ||
43 | 44 | flex-basis: 100% |
44 | 45 | margin-bottom: .6rem |
45 | 46 | } |
46 | 47 | |
47 | - div.Button.-channel {} | |
48 | + div.Button.-channel { | |
49 | + margin-right: 1rem | |
50 | + } | |
51 | + div.Likes { | |
52 | + } | |
48 | 53 | } |
49 | 54 | |
50 | 55 | div.author { |
51 | 56 | display: flex |
app/page/settings.js | ||
---|---|---|
@@ -1,15 +1,18 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const { h } = require('mutant') | |
2 | +const { h, computed } = require('mutant') | |
3 | +const electron = require('electron') | |
3 | 4 | |
4 | 5 | exports.gives = nest('app.page.settings') |
5 | 6 | |
6 | 7 | exports.needs = nest({ |
7 | 8 | 'about.html.image': 'first', |
8 | 9 | 'about.obs.name': 'first', |
10 | + 'about.obs.description': 'first', | |
9 | 11 | 'history.sync.push': 'first', |
10 | 12 | 'history.obs.store': 'first', |
11 | 13 | 'keys.sync.id': 'first', |
14 | + 'message.html.markdown': 'first', | |
12 | 15 | 'settings.sync.get': 'first', |
13 | 16 | 'settings.sync.set': 'first', |
14 | 17 | 'settings.obs.get': 'first', |
15 | 18 | 'translations.sync.strings': 'first', |
@@ -43,9 +46,9 @@ | ||
43 | 46 | const strings = api.translations.sync.strings() |
44 | 47 | const currentLanguage = api.settings.sync.get('language') |
45 | 48 | |
46 | 49 | const editProfile = () => api.history.sync.push({ |
47 | - page:'userEdit', | |
50 | + page: 'userEdit', | |
48 | 51 | feed, |
49 | 52 | callback: (err, didEdit) => { |
50 | 53 | if (err) throw new Error ('Error editing profile', err) |
51 | 54 | api.history.sync.push({ page: 'settings' }) |
@@ -54,25 +57,31 @@ | ||
54 | 57 | |
55 | 58 | return h('Page -settings', [ |
56 | 59 | h('div.content', [ |
57 | 60 | h('h1', strings.settingsPage.title), |
58 | - h('section -profile', [ | |
59 | - h('header', strings.settingsPage.section.profile), | |
60 | - h('div.profile', [ | |
61 | - h('div.name', api.about.obs.name(feed)), | |
62 | - api.about.html.image(feed), | |
61 | + h('section -avatar', [ | |
62 | + h('div.left'), | |
63 | + h('div.right', api.about.html.image(feed)), | |
64 | + ]), | |
65 | + h('section -name', [ | |
66 | + h('div.left', strings.settingsPage.section.name), | |
67 | + h('div.right', [ | |
68 | + api.about.obs.name(feed), | |
69 | + h('i.fa.fa-pencil', { 'ev-click': editProfile }) | |
63 | 70 | ]), |
64 | - h('div.actions', [ | |
65 | - h('Button', { 'ev-click': editProfile }, [ | |
66 | - strings.settingsPage.action.edit, | |
67 | - h('i.fa.fa-pencil') | |
68 | - ]) | |
69 | - ]) | |
70 | 71 | ]), |
72 | + h('section -introduction', [ | |
73 | + h('div.left', strings.settingsPage.section.introduction), | |
74 | + h('div.right', computed(api.about.obs.description(feed), d => api.message.html.markdown(d || ''))) | |
75 | + ]), | |
71 | 76 | h('section -language', [ |
72 | - h('header', strings.settingsPage.section.language), | |
73 | - h('div.languages', LANGUAGES.map(Language)) | |
74 | - ]) | |
77 | + h('div.left', strings.settingsPage.section.language), | |
78 | + h('div.right', LANGUAGES.map(Language)) | |
79 | + ]), | |
80 | + h('section -zoom', [ | |
81 | + h('div.left', strings.settingsPage.section.zoom), | |
82 | + h('div.right', [ zoomButton(-0.1, '-'), zoomButton(+0.1, '+') ]) | |
83 | + ]), | |
75 | 84 | ]) |
76 | 85 | ]) |
77 | 86 | |
78 | 87 | function Language (lang) { |
@@ -83,11 +92,25 @@ | ||
83 | 92 | { |
84 | 93 | 'ev-click': () => selectLang(lang), |
85 | 94 | className |
86 | 95 | }, |
87 | - lang | |
96 | + strings.languages[lang] | |
88 | 97 | ) |
89 | 98 | } |
90 | 99 | |
100 | + function zoomButton (increment, symbol) { | |
101 | + const { getCurrentWebContents } = electron.remote | |
102 | + return h('Button -language', | |
103 | + { | |
104 | + 'ev-click': () => { | |
105 | + var zoomFactor = api.settings.sync.get('ticktack.electron.zoomFactor', 1) | |
106 | + var newZoomFactor = zoomFactor + increment | |
107 | + var zoomFactor = api.settings.sync.set('ticktack.electron.zoomFactor', newZoomFactor) | |
108 | + getCurrentWebContents().setZoomFactor(newZoomFactor) | |
109 | + } | |
110 | + }, | |
111 | + symbol | |
112 | + ) | |
113 | + } | |
91 | 114 | } |
92 | 115 | } |
93 | 116 |
app/page/settings.mcss | ||
---|---|---|
@@ -1,56 +1,61 @@ | ||
1 | 1 | Page -settings { |
2 | 2 | padding-top: 1rem |
3 | - $backgroundGrey | |
3 | + background: #fff | |
4 | 4 | |
5 | 5 | div.content { |
6 | - background: #fff | |
7 | 6 | padding: 1rem |
8 | 7 | $maxWidthSmaller |
9 | 8 | |
10 | 9 | h1 { |
10 | + font-size: 1.5rem | |
11 | + font-weight: 300 | |
12 | + | |
13 | + padding-bottom: 1rem | |
14 | + border-bottom: 1px solid gainsboro | |
11 | 15 | margin-top: 0 |
16 | + margin-bottom: 4rem | |
12 | 17 | } |
13 | 18 | |
14 | 19 | section { |
15 | - padding-bottom: 2rem | |
16 | - margin-bottom: 2rem | |
20 | + display: flex | |
21 | + align-content: center | |
17 | 22 | |
18 | - header { | |
19 | - font-size: 1.4rem | |
20 | - margin-bottom: 1rem | |
21 | - } | |
23 | + div { | |
24 | + padding: .5rem | |
22 | 25 | |
23 | - -profile { | |
24 | - div.profile { | |
25 | - display: flex | |
26 | - flex-direction: column | |
26 | + display: flex | |
27 | + align-items: center | |
27 | 28 | |
28 | - div.name { | |
29 | - margin-bottom: .5rem | |
30 | - } | |
31 | - img.Avatar { | |
32 | - width: 8rem | |
33 | - height: 8rem | |
34 | - } | |
35 | - margin-bottom: .5rem | |
29 | + img.Avatar { | |
30 | + $circleLarge | |
31 | + margin-bottom: 1rem | |
36 | 32 | } |
37 | 33 | |
38 | - div.actions { | |
39 | - display:flex | |
34 | + i.fa { | |
35 | + cursor: pointer | |
36 | + margin: 0 .5rem | |
40 | 37 | |
41 | - div.Button { | |
42 | - i.fa { margin-left: .4rem } | |
38 | + :hover { | |
39 | + $colorFontPrimary | |
43 | 40 | } |
44 | 41 | } |
45 | 42 | } |
43 | + div.left { | |
44 | + flex-basis: 40% | |
45 | + $colorFontSubtle | |
46 | 46 | |
47 | - -language { | |
48 | - div.languages { | |
49 | - display: flex | |
50 | - } | |
47 | + justify-content: flex-end | |
51 | 48 | } |
49 | + div.right { | |
50 | + flex-basis: 60% | |
51 | + justify-content: flex-start | |
52 | + } | |
52 | 53 | } |
54 | + | |
55 | + section -introduction { | |
56 | + margin-bottom: 2rem | |
57 | + } | |
53 | 58 | } |
54 | 59 | } |
55 | 60 | |
56 | 61 | Button -language { |
app/page/userEdit.js | ||
---|---|---|
@@ -20,10 +20,11 @@ | ||
20 | 20 | |
21 | 21 | const options = Object.assign({}, location, { |
22 | 22 | feed, |
23 | 23 | labels: { |
24 | + avatar: strings.userEdit.section.avatar, | |
24 | 25 | name: strings.userEdit.section.name, |
25 | - avatar: strings.userEdit.section.avatar, | |
26 | + description: strings.userEdit.section.introduction, | |
26 | 27 | instructionCrop: strings.userEdit.instruction.crop, |
27 | 28 | okay: strings.userEdit.action.okay, |
28 | 29 | cancel: strings.userEdit.action.cancel, |
29 | 30 | save: strings.userEdit.action.save, |
app/page/userEdit.mcss | ||
---|---|---|
@@ -4,7 +4,25 @@ | ||
4 | 4 | } |
5 | 5 | div.content { |
6 | 6 | $maxWidthSmaller |
7 | 7 | |
8 | + div.PatchProfileEdit { | |
9 | + section.-avatar { | |
10 | + div.input { | |
11 | + $circleLarge | |
12 | + | |
13 | + img.Avatar { | |
14 | + $circleLarge | |
15 | + } | |
16 | + | |
17 | + input { | |
18 | + ::before { | |
19 | + $circleLarge | |
20 | + } | |
21 | + } | |
22 | + } | |
23 | + } | |
24 | + } | |
25 | + | |
8 | 26 | } |
9 | 27 | } |
10 | 28 |
app/page/userShow.js | ||
---|---|---|
@@ -7,13 +7,18 @@ | ||
7 | 7 | |
8 | 8 | exports.needs = nest({ |
9 | 9 | 'about.html.avatar': 'first', |
10 | 10 | 'about.obs.name': 'first', |
11 | + 'about.obs.description': 'first', | |
12 | + 'app.html.context': 'first', | |
11 | 13 | 'app.html.link': 'first', |
12 | 14 | 'app.html.blogCard': 'first', |
15 | + 'app.html.blogNav': 'first', | |
16 | + 'app.html.scroller': 'first', | |
13 | 17 | 'contact.html.follow': 'first', |
18 | + 'feed.pull.profile': 'first', | |
14 | 19 | 'feed.pull.rollup': 'first', |
15 | - 'sbot.pull.userFeed': 'first', | |
20 | + 'message.html.markdown': 'first', | |
16 | 21 | 'keys.sync.id': 'first', |
17 | 22 | 'translations.sync.strings': 'first', |
18 | 23 | 'unread.sync.isUnread': 'first' |
19 | 24 | }) |
@@ -22,73 +27,62 @@ | ||
22 | 27 | var isUnread = api.unread.sync.isUnread |
23 | 28 | return nest('app.page.userShow', userShow) |
24 | 29 | |
25 | 30 | function userShow (location) { |
26 | - | |
27 | 31 | const { feed } = location |
28 | 32 | const myId = api.keys.sync.id() |
29 | - const name = api.about.obs.name(feed) | |
30 | 33 | |
31 | 34 | const strings = api.translations.sync.strings() |
32 | 35 | |
33 | - // const { followers } = api.contact.obs | |
34 | - | |
35 | - // const youFollowThem = computed(followers(feed), followers => followers.includes(myId)) | |
36 | - // const theyFollowYou = computed(followers(myId), followers => followers.includes(feed)) | |
37 | - // const youAreFriends = computed([youFollowThem, theyFollowYou], (a, b) => a && b) | |
38 | - | |
39 | - // const ourRelationship = computed( | |
40 | - // [youAreFriends, youFollowThem, theyFollowYou], | |
41 | - // (youAreFriends, youFollowThem, theyFollowYou) => { | |
42 | - // if (youAreFriends) return strings.userShow.state.friends | |
43 | - // if (theyFollowYou) return strings.userShow.state.theyFollow | |
44 | - // if (youFollowThem) return strings.userShow.state.youFollow | |
45 | - // } | |
46 | - // ) | |
47 | - | |
48 | 36 | const Link = api.app.html.link |
49 | 37 | const userEditButton = Link({ page: 'userEdit', feed }, h('i.fa.fa-pencil')) |
50 | 38 | const directMessageButton = Link({ page: 'threadNew', feed }, h('Button', strings.userShow.action.directMessage)) |
51 | 39 | |
52 | 40 | const BLOG_TYPES = ['blog', 'post'] |
53 | - const blogs = MutantArray() | |
54 | - pull( | |
55 | - api.sbot.pull.userFeed({id: feed, reverse: true, live: false}), | |
56 | - pull.filter(msg => BLOG_TYPES.includes(get(msg, 'value.content.type'))), | |
57 | - // pull.filter(msg => get(msg, 'value.content.root') === undefined), | |
58 | - api.feed.pull.rollup(), | |
59 | - //unread state should not be in this file... | |
60 | - pull.through(function (blog) { | |
61 | - if(isUnread(blog)) | |
62 | - blog.unread = true | |
63 | - blog.replies.forEach(function (data) { | |
64 | - if(isUnread(data)) | |
65 | - blog.unread = data.unread = true | |
66 | - }) | |
67 | - }), | |
68 | - pull.drain(blogs.push) | |
69 | - // TODO - new Scroller ? | |
70 | - ) | |
71 | 41 | |
72 | - return h('Page -userShow', {title: name}, [ | |
73 | - h('div.content', [ | |
74 | - h('section.about', [ | |
75 | - api.about.html.avatar(feed, 'large'), | |
76 | - h('h1', [ | |
77 | - name, | |
78 | - feed === myId // Only expose own profile editing right now | |
79 | - ? userEditButton | |
80 | - : '' | |
81 | - ]), | |
82 | - feed !== myId | |
83 | - ? h('div.actions', [ | |
84 | - api.contact.html.follow(feed), | |
85 | - h('div.directMessage', directMessageButton) | |
86 | - ]) | |
87 | - : '', | |
42 | + // TODO return some of this ? | |
43 | + // but maybe this shouldn't be done here ? | |
44 | + // pull.through(function (blog) { | |
45 | + // if(isUnread(blog)) | |
46 | + // blog.unread = true | |
47 | + // blog.replies.forEach(function (data) { // this was fed rollups | |
48 | + // if(isUnread(data)) | |
49 | + // blog.unread = data.unread = true | |
50 | + // }) | |
51 | + // }), | |
52 | + | |
53 | + const prepend = [ | |
54 | + api.app.html.blogNav(location), | |
55 | + h('section.about', [ | |
56 | + api.about.html.avatar(feed, 'large'), | |
57 | + h('h1', [ | |
58 | + api.about.obs.name(feed), | |
59 | + feed === myId // Only expose own profile editing right now | |
60 | + ? userEditButton | |
61 | + : '' | |
88 | 62 | ]), |
89 | - h('section.blogs', map(blogs, api.app.html.blogCard)) | |
90 | - ]) | |
63 | + h('div.introduction', computed(api.about.obs.description(feed), d => api.message.html.markdown(d || ''))), | |
64 | + feed !== myId | |
65 | + ? h('div.actions', [ | |
66 | + api.contact.html.follow(feed), | |
67 | + h('div.directMessage', directMessageButton) | |
68 | + ]) | |
69 | + : '', | |
70 | + ]), | |
71 | + ] | |
72 | + | |
73 | + return h('Page -userShow', [ | |
74 | + api.app.html.context(location), | |
75 | + api.app.html.scroller({ | |
76 | + classList: ['content'], | |
77 | + prepend, | |
78 | + stream: api.feed.pull.profile(feed), | |
79 | + filter: () => pull( | |
80 | + pull.filter(msg => get(msg, 'value.content.root') === undefined), | |
81 | + pull.filter(msg => BLOG_TYPES.includes(get(msg, 'value.content.type'))) | |
82 | + ), | |
83 | + render: api.app.html.blogCard | |
84 | + }) | |
91 | 85 | ]) |
92 | 86 | } |
93 | 87 | } |
94 | 88 |
app/page/userShow.mcss | ||
---|---|---|
@@ -1,42 +1,59 @@ | ||
1 | 1 | Page -userShow { |
2 | - div.content { | |
3 | - section.about { | |
4 | - margin-top: 4rem | |
5 | - margin-bottom: 4rem | |
2 | + div.content { padding: 0 } | |
6 | 3 | |
7 | - display: flex | |
8 | - flex-direction: column | |
9 | - align-items: center | |
4 | + div.Scroller.content { | |
5 | + section.top { | |
6 | + section.about { | |
7 | + margin-top: 4rem | |
8 | + margin-bottom: 4rem | |
10 | 9 | |
11 | - img.Avatar { | |
12 | - } | |
10 | + display: flex | |
11 | + flex-direction: column | |
12 | + align-items: center | |
13 | 13 | |
14 | - h1 { | |
15 | - font-weight: 300 | |
16 | - font-size: 1rem | |
17 | - | |
18 | - display: flex | |
19 | - div.Link { | |
20 | - margin-left: .5rem | |
14 | + img.Avatar { | |
21 | 15 | } |
22 | - } | |
16 | + div.introduction { | |
17 | + $maxWidthSmaller | |
18 | + } | |
23 | 19 | |
24 | - div.actions { | |
25 | - display: flex | |
26 | - | |
27 | - div.Follow { | |
28 | - margin-right: 1rem | |
20 | + h1 { | |
21 | + font-weight: 300 | |
22 | + font-size: 1rem | |
23 | + | |
24 | + display: flex | |
25 | + div.Link { | |
26 | + margin-left: .5rem | |
27 | + } | |
29 | 28 | } |
30 | 29 | |
31 | - div.directMessage { | |
30 | + div.actions { | |
31 | + display: flex | |
32 | + | |
33 | + div.Follow { | |
34 | + margin-right: 1rem | |
35 | + } | |
36 | + | |
37 | + div.directMessage { | |
38 | + } | |
32 | 39 | } |
33 | 40 | } |
34 | 41 | } |
35 | 42 | |
36 | - section.blogs { | |
43 | + section.content { | |
44 | + background-color: #fff | |
45 | + $maxWidth | |
46 | + margin: .8rem auto | |
47 | + padding: .5rem 2rem | |
48 | + | |
49 | + display: flex | |
50 | + flex-wrap: wrap | |
51 | + | |
37 | 52 | div.BlogCard { |
38 | - margin-bottom: .5rem | |
53 | + flex-basis: 100% | |
54 | + border-bottom: 1px solid rgba(0,0,0, .1) | |
55 | + /* margin-bottom: .5rem */ | |
39 | 56 | |
40 | 57 | div.context { |
41 | 58 | div.Link { display: none } |
42 | 59 | div.name { display: none } |
app/sync/initialize/suggests.js | ||
---|---|---|
@@ -3,9 +3,10 @@ | ||
3 | 3 | exports.gives = nest('app.sync.initialize') |
4 | 4 | |
5 | 5 | exports.needs = nest({ |
6 | 6 | 'about.async.suggest': 'first', |
7 | - 'channel.async.suggest': 'first' | |
7 | + 'channel.async.suggest': 'first', | |
8 | + // 'channel.obs.recent': 'first' | |
8 | 9 | }) |
9 | 10 | |
10 | 11 | exports.create = (api) => { |
11 | 12 | var nav = null |
@@ -13,8 +14,9 @@ | ||
13 | 14 | return nest({ |
14 | 15 | 'app.sync.initialize': function initializeSuggests () { |
15 | 16 | api.about.async.suggest() |
16 | 17 | api.channel.async.suggest() |
18 | + // api.channel.obs.recent()() TODO - figure out how to initialise this store | |
17 | 19 | } |
18 | 20 | }) |
19 | 21 | } |
20 | 22 |
app/sync/initialize/zoomMemory.js | ||
---|---|---|
@@ -1,0 +1,41 @@ | ||
1 | +const nest = require('depnest') | |
2 | +const electron = require('electron') | |
3 | + | |
4 | +exports.gives = nest('app.sync.initialize') | |
5 | + | |
6 | +exports.needs = nest({ | |
7 | + 'settings.sync.get': 'first', | |
8 | + 'settings.sync.set': 'first' | |
9 | +}) | |
10 | + | |
11 | +exports.create = (api) => { | |
12 | + return nest('app.sync.initialize', zoomMemory) | |
13 | + | |
14 | + function zoomMemory() { | |
15 | + const { getCurrentWebContents, getCurrentWindow } = electron.remote | |
16 | + | |
17 | + window.addEventListener('resize', () => { | |
18 | + var wc = getCurrentWebContents() | |
19 | + wc && wc.getZoomFactor(zf => { | |
20 | + console.log(zf) | |
21 | + api.settings.sync.set({ | |
22 | + ticktack: { | |
23 | + electron: { | |
24 | + zoomFactor: zf, | |
25 | + windowBounds: getCurrentWindow().getBounds() | |
26 | + } | |
27 | + } | |
28 | + }) | |
29 | + }) | |
30 | + }) | |
31 | + | |
32 | + var zoomFactor = api.settings.sync.get('ticktack.electron.zoomFactor') | |
33 | + if (zoomFactor) | |
34 | + getCurrentWebContents().setZoomFactor(zoomFactor) | |
35 | + | |
36 | + var bounds = api.settings.sync.get('ticktack.electron.windowBounds') | |
37 | + if (bounds) | |
38 | + getCurrentWindow().setBounds(bounds) | |
39 | + } | |
40 | +} | |
41 | + |
message/html/likes.mcss | ||
---|---|---|
@@ -1,4 +1,15 @@ | ||
1 | 1 | Likes { |
2 | 2 | cursor: pointer |
3 | + min-width: 2.5rem | |
4 | + | |
5 | + display: flex | |
6 | + align-items: center | |
7 | + | |
8 | + i { | |
9 | + margin-right: .4rem | |
10 | + } | |
11 | + i.fa-heart { | |
12 | + $colorFontPrimary | |
13 | + } | |
3 | 14 | } |
4 | 15 |
package-lock.json | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 211063 bytes New file size: 211063 bytes |
package.json | ||
---|---|---|
@@ -1,16 +1,17 @@ | ||
1 | 1 | { |
2 | 2 | "name": "ticktack", |
3 | - "version": "0.1.3", | |
3 | + "version": "0.2.1", | |
4 | 4 | "description": "", |
5 | 5 | "main": "index.js", |
6 | 6 | "scripts": { |
7 | 7 | "rebuild": "cross-script npm rebuild --runtime=electron \"--target=$(electron -v)\" \"--abi=$(electron --abi)\" --disturl=https://atom.io/download/atom-shell", |
8 | 8 | "start": "electron .", |
9 | 9 | "dev": "ssb_appname=ssb electro main.js", |
10 | 10 | "postinstall": "echo 'REMEMBER: npm run rebuild'", |
11 | 11 | "test": "npm run test:deps", |
12 | - "test:deps": "dependency-check package.json --entry main.js --entry background-process.js && dependency-check package.json --entry main.js --entry background-process.js --extra --no-dev" | |
12 | + "test:deps": "dependency-check package.json --entry main.js --entry background-process.js && dependency-check package.json --entry main.js --entry background-process.js --extra --no-dev", | |
13 | + "test:i18n": "node translations/checker.js" | |
13 | 14 | }, |
14 | 15 | "repository": { |
15 | 16 | "type": "git", |
16 | 17 | "url": "ssb://%tkJPTTaxOzfLbsewZmgC9CslSER0ntjQOcyhIk6y/cQ=.sha256" |
@@ -37,9 +38,9 @@ | ||
37 | 38 | "mutant": "^3.21.2", |
38 | 39 | "mutant-scroll": "0.0.5", |
39 | 40 | "open-external": "^0.1.1", |
40 | 41 | "patch-history": "^1.0.0", |
41 | - "patch-profile": "^1.0.2", | |
42 | + "patch-profile": "^1.0.3", | |
42 | 43 | "patch-settings": "^1.0.0", |
43 | 44 | "patch-suggest": "^1.0.1", |
44 | 45 | "patchcore": "^1.12.0", |
45 | 46 | "pull-next": "^1.0.1", |
styles/button.mcss | ||
---|---|---|
@@ -2,9 +2,9 @@ | ||
2 | 2 | font-family: arial |
3 | 3 | $backgroundPrimaryText |
4 | 4 | |
5 | 5 | min-width: 5rem |
6 | - height: 1.4em | |
6 | + height: 1.4rem | |
7 | 7 | padding: .2rem 1rem |
8 | 8 | |
9 | 9 | border: 1px #b9b9b9 solid |
10 | 10 | border-radius: 10rem |
styles/global.mcss | ||
---|---|---|
@@ -1,4 +1,8 @@ | ||
1 | +html { | |
2 | + font-size: 17px | |
3 | +} | |
4 | + | |
1 | 5 | body { |
2 | 6 | $fontBasic |
3 | 7 | $backgroundPrimaryText |
4 | 8 |
styles/mixins.js | ||
---|---|---|
@@ -11,10 +11,10 @@ | ||
11 | 11 | |
12 | 12 | const mainMixins = ` |
13 | 13 | $fontBasic { |
14 | 14 | font-family: arial |
15 | + line-height: 1.2 | |
15 | 16 | font-size: 1rem |
16 | - line-height: 1.2 | |
17 | 17 | } |
18 | 18 | |
19 | 19 | $maxWidth { |
20 | 20 | max-width: 1000px |
@@ -45,9 +45,9 @@ | ||
45 | 45 | color: #222 |
46 | 46 | } |
47 | 47 | |
48 | 48 | $colorFontPrimary { |
49 | - color: #5c6bc0 | |
49 | + color: #2f63ad | |
50 | 50 | } |
51 | 51 | |
52 | 52 | $colorFontSubtle { |
53 | 53 | color: #999 |
@@ -92,9 +92,9 @@ | ||
92 | 92 | height: 3.5rem |
93 | 93 | border-radius: 4rem |
94 | 94 | } |
95 | 95 | |
96 | -$circlelarge { | |
96 | +$circleLarge { | |
97 | 97 | min-width: 8rem |
98 | 98 | min-height: 8rem |
99 | 99 | width: 8rem |
100 | 100 | height: 8rem |
translations/en.js | ||
---|---|---|
@@ -46,10 +46,12 @@ | ||
46 | 46 | action: { |
47 | 47 | edit: 'Edit', |
48 | 48 | }, |
49 | 49 | section: { |
50 | + name: 'Name', | |
51 | + introduction: 'Introduction', | |
50 | 52 | language: 'Language', |
51 | - profile: 'Profile', | |
53 | + zoom: 'Zoom' | |
52 | 54 | } |
53 | 55 | }, |
54 | 56 | threadNew: { |
55 | 57 | pageTitle: 'New Thread', |
@@ -63,10 +65,11 @@ | ||
63 | 65 | }, |
64 | 66 | threadShow: 'Direct Messages', |
65 | 67 | userEdit: { |
66 | 68 | section: { |
69 | + avatar: 'Avatar', | |
67 | 70 | name: 'Name', |
68 | - avatar: 'Avatar' | |
71 | + introduction: 'Introduction', | |
69 | 72 | }, |
70 | 73 | instruction: { |
71 | 74 | crop: 'Click and drag to crop your avatar' |
72 | 75 | }, |
@@ -95,6 +98,11 @@ | ||
95 | 98 | userConversationsWith: 'conversations you\'ve had with', |
96 | 99 | follow: "Follow", |
97 | 100 | friendsInCommon: 'friends in common' |
98 | 101 | } |
102 | + }, | |
103 | + languages: { | |
104 | + en: 'English', | |
105 | + zh: 'Chinese' | |
99 | 106 | } |
107 | + | |
100 | 108 | } |
translations/zh.js | ||
---|---|---|
@@ -1,4 +1,5 @@ | ||
1 | + | |
1 | 2 | module.exports = { |
2 | 3 | loading: '加载中...', |
3 | 4 | optionalField: '可选', |
4 | 5 | sendMessage: '发送', |
@@ -8,8 +9,27 @@ | ||
8 | 9 | home: '主页', |
9 | 10 | error: '错误', |
10 | 11 | errorNotFound: '找不到此页面', |
11 | 12 | groupNew: '新建群组', |
13 | + writeMessage: '发私信', | |
14 | + peopleNearby: '附件的朋友', | |
15 | + blogIndex: { | |
16 | + title: '发现' | |
17 | + }, | |
18 | + blogNew: { | |
19 | + field: { | |
20 | + title: '标题' | |
21 | + }, | |
22 | + actions: { | |
23 | + edit: '编辑', | |
24 | + preview: '预览', | |
25 | + writeBlog: '撰文' | |
26 | + } | |
27 | + }, | |
28 | + blogNav: { | |
29 | + blogsAll: '最新', | |
30 | + blogSearch: '搜索' | |
31 | + }, | |
12 | 32 | groupFind: { |
13 | 33 | action: { |
14 | 34 | findAGroup: '查找群组', |
15 | 35 | newGroup: '创建此群组' |
@@ -28,9 +48,12 @@ | ||
28 | 48 | edit: '编辑', |
29 | 49 | }, |
30 | 50 | section: { |
31 | 51 | language: '语言', |
32 | - profile: '自我介绍' | |
52 | + profile: '自我介绍', | |
53 | + name: '名称', | |
54 | + introduction: '简介', | |
55 | + zoom: '放大' | |
33 | 56 | } |
34 | 57 | }, |
35 | 58 | threadNew: { |
36 | 59 | pageTitle: '新建话题', |
@@ -45,9 +68,10 @@ | ||
45 | 68 | threadShow: '所有私信', |
46 | 69 | userEdit: { |
47 | 70 | section: { |
48 | 71 | name: '名称', |
49 | - avatar: '头像' | |
72 | + avatar: '头像', | |
73 | + introduction: '简介' | |
50 | 74 | }, |
51 | 75 | instruction: { |
52 | 76 | crop: '点击编辑头像' |
53 | 77 | }, |
@@ -76,6 +100,10 @@ | ||
76 | 100 | userConversationsWith: '参与的话题', |
77 | 101 | follow: '关注', |
78 | 102 | friendsInCommon: '共同的好友' |
79 | 103 | } |
104 | + }, | |
105 | + languages: { | |
106 | + en: '英文', | |
107 | + zh: '中文' | |
80 | 108 | } |
81 | 109 | } |
Built with git-ssb-web