git ssb

10+

Matt McKegg / patchwork



Tree: 81be424f72e758de508ff828259c7c30cea65236

Files: 81be424f72e758de508ff828259c7c30cea65236 / main-window.js

5803 bytesRaw
1var combine = require('depject')
2var entry = require('depject/entry')
3var electron = require('electron')
4var h = require('mutant/h')
5var Value = require('mutant/value')
6var when = require('mutant/when')
7var computed = require('mutant/computed')
8var toCollection = require('mutant/dict-to-collection')
9var MutantDict = require('mutant/dict')
10var MutantMap = require('mutant/map')
11var Url = require('url')
12var insertCss = require('insert-css')
13var nest = require('depnest')
14var LatestUpdate = require('./lib/latest-update')
15
16require('./lib/context-menu-and-spellcheck.js')
17
18module.exports = function (config) {
19 var sockets = combine(
20 overrideConfig(config),
21 require('./modules'),
22 require('./plugs'),
23 require('patchcore'),
24 require('./overrides')
25 )
26
27 var api = entry(sockets, nest({
28 'page.html.render': 'first',
29 'keys.sync.id': 'first',
30 'blob.sync.url': 'first',
31 'app.html.search': 'first'
32 }))
33
34 var renderPage = api.page.html.render
35 var id = api.keys.sync.id()
36 var latestUpdate = LatestUpdate()
37
38 var forwardHistory = []
39 var backHistory = []
40
41 var views = MutantDict({
42 // preload tabs (and subscribe to update notifications)
43 '/public': renderPage('/public'),
44 '/private': renderPage('/private'),
45 [id]: renderPage(id),
46 '/mentions': renderPage('/mentions')
47 })
48
49 var lastViewed = {}
50 var defaultViews = views.keys()
51
52 // delete cached view after 5 mins of last seeing
53 setInterval(() => {
54 views.keys().forEach((view) => {
55 if (!defaultViews.includes(view)) {
56 if (lastViewed[view] !== true && Date.now() - lastViewed[view] > (5 * 60e3) && view !== currentView()) {
57 views.delete(view)
58 }
59 }
60 })
61 }, 60e3)
62
63 var canGoForward = Value(false)
64 var canGoBack = Value(false)
65 var currentView = Value('/public')
66
67 var viewCollection = toCollection(views)
68
69 var mainElement = h('div.main', MutantMap(viewCollection, (item) => {
70 return h('div.view', {
71 hidden: computed([item.key, currentView], (a, b) => a !== b)
72 }, [ item.value ])
73 }))
74
75 insertCss(require('./styles'))
76
77 var container = h(`MainWindow -${process.platform}`, {
78 events: {
79 click: catchLinks
80 }
81 }, [
82 h('div.top', [
83 h('span.history', [
84 h('a', {
85 'ev-click': goBack,
86 classList: [ when(canGoBack, '-active') ]
87 }, '<'),
88 h('a', {
89 'ev-click': goForward,
90 classList: [ when(canGoForward, '-active') ]
91 }, '>')
92 ]),
93 h('span.nav', [
94 tab('Public', '/public'),
95 tab('Private', '/private')
96 ]),
97 h('span.appTitle', ['Patchwork']),
98 h('span', [ api.app.html.search(setView) ]),
99 h('span.nav', [
100 tab('Profile', id),
101 tab('Mentions', '/mentions')
102 ])
103 ]),
104 when(latestUpdate,
105 h('div.info', [
106 h('a.message -update', { href: 'https://github.com/mmckegg/patchwork-next/releases' }, [
107 h('strong', ['Patchwork ', latestUpdate, ' has been released.']), ' Click here for more info!'
108 ])
109 ])
110 ),
111 mainElement
112 ])
113
114 return container
115
116 // scoped
117
118 function catchLinks (ev) {
119 if (ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey || ev.defaultPrevented) {
120 return true
121 }
122
123 var anchor = null
124 for (var n = ev.target; n.parentNode; n = n.parentNode) {
125 if (n.nodeName === 'A') {
126 anchor = n
127 break
128 }
129 }
130 if (!anchor) return true
131
132 var href = anchor.getAttribute('href')
133
134 if (href) {
135 var url = Url.parse(href)
136 if (url.host) {
137 electron.shell.openExternal(href)
138 } else if (href.charAt(0) === '&') {
139 electron.shell.openExternal(api.blob.sync.url(href))
140 } else if (href !== '#') {
141 setView(href)
142 }
143 }
144
145 ev.preventDefault()
146 ev.stopPropagation()
147 }
148
149 function tab (name, view) {
150 var instance = views.get(view)
151 lastViewed[view] = true
152 return h('a', {
153 'ev-click': function (ev) {
154 if (instance.pendingUpdates && instance.pendingUpdates() && instance.reload) {
155 instance.reload()
156 }
157 },
158 href: view,
159 classList: [
160 when(selected(view), '-selected')
161 ]
162 }, [
163 name,
164 when(instance.pendingUpdates, [
165 ' (', instance.pendingUpdates, ')'
166 ])
167 ])
168 }
169
170 function goBack () {
171 if (backHistory.length) {
172 canGoForward.set(true)
173 forwardHistory.push(currentView())
174
175 var view = backHistory.pop()
176 if (!views.has(view)) {
177 views.put(view, renderPage(view))
178 }
179
180 currentView.set(view)
181 canGoBack.set(backHistory.length > 0)
182 }
183 }
184
185 function goForward () {
186 if (forwardHistory.length) {
187 backHistory.push(currentView())
188
189 var view = forwardHistory.pop()
190 if (!views.has(view)) {
191 views.put(view, renderPage(view))
192 }
193
194 currentView.set(view)
195 canGoForward.set(forwardHistory.length > 0)
196 canGoBack.set(true)
197 }
198 }
199
200 function setView (view) {
201 if (!views.has(view)) {
202 views.put(view, renderPage(view))
203 }
204
205 if (lastViewed[view] !== true) {
206 lastViewed[view] = Date.now()
207 }
208
209 if (currentView() && lastViewed[currentView()] !== true) {
210 lastViewed[currentView()] = Date.now()
211 }
212
213 if (view !== currentView()) {
214 canGoForward.set(false)
215 canGoBack.set(true)
216 forwardHistory.length = 0
217 backHistory.push(currentView())
218 currentView.set(view)
219 }
220 }
221
222 function selected (view) {
223 return computed([currentView, view], (currentView, view) => {
224 return currentView === view
225 })
226 }
227}
228
229function overrideConfig (config) {
230 return [{
231 gives: nest('config.sync.load'),
232 create: function (api) {
233 return nest('config.sync.load', () => config)
234 }
235 }]
236}
237

Built with git-ssb-web