Browse code
fix: solve too many pushState calls
fiddlerwoaroof authored on 14/10/2022 04:24:28
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -1,192 +1,209 @@ |
1 | 1 |
root = new Vue({ |
2 |
- el: '#container', |
|
3 |
- data: { |
|
4 |
- "pull_time": null, |
|
5 |
- "feed_urls": [], |
|
6 |
- feeds: { |
|
7 |
- feeds: [] |
|
8 |
- }, |
|
9 |
- collapsed: false, |
|
10 |
- |
|
11 |
- current_feed: { |
|
12 |
- metadata: { |
|
13 |
- description: null, |
|
14 |
- fetch_url: null, |
|
15 |
- link: null, |
|
16 |
- title: null, |
|
17 |
- }, |
|
18 |
- base_path: null, |
|
19 |
- items: [], |
|
20 |
- }, |
|
21 |
- |
|
22 |
- current_item: { |
|
23 |
- title: null, |
|
24 |
- date: null, |
|
25 |
- author: null, |
|
26 |
- id: null, |
|
27 |
- link: null, |
|
28 |
- content: null, |
|
29 |
- }, |
|
30 |
- |
|
31 |
- feed_item_counts: {}, |
|
32 |
- |
|
33 |
- likes: [], |
|
34 |
- show_likes: true, |
|
2 |
+ el: "#container", |
|
3 |
+ data: { |
|
4 |
+ pull_time: null, |
|
5 |
+ feed_urls: [], |
|
6 |
+ feeds: { |
|
7 |
+ feeds: [], |
|
8 |
+ }, |
|
9 |
+ collapsed: false, |
|
10 |
+ |
|
11 |
+ current_feed: { |
|
12 |
+ metadata: { |
|
13 |
+ description: null, |
|
14 |
+ fetch_url: null, |
|
15 |
+ link: null, |
|
16 |
+ title: null, |
|
17 |
+ }, |
|
18 |
+ base_path: null, |
|
19 |
+ items: [], |
|
35 | 20 |
}, |
36 | 21 |
|
37 |
- computed: { |
|
38 |
- feed_visible() { |
|
39 |
- return (!this.show_likes) && |
|
40 |
- this.current_feed.metadata.title !== null && |
|
41 |
- this.current_feed.items.length > 0; |
|
42 |
- }, |
|
43 |
- |
|
44 |
- item_content() { |
|
45 |
- let result = null; |
|
46 |
- if (this.current_item.content !== null) { |
|
47 |
- result = DOMPurify.sanitize(this.current_item.content, { |
|
48 |
- FORBID_TAG: ['style'], |
|
49 |
- FORBID_ATTR: ['style'], |
|
50 |
- }); |
|
51 |
- } |
|
52 |
- return result; |
|
53 |
- }, |
|
22 |
+ current_item: { |
|
23 |
+ title: null, |
|
24 |
+ date: null, |
|
25 |
+ author: null, |
|
26 |
+ id: null, |
|
27 |
+ link: null, |
|
28 |
+ content: null, |
|
29 |
+ path: null, |
|
30 |
+ }, |
|
31 |
+ |
|
32 |
+ feed_item_counts: {}, |
|
33 |
+ |
|
34 |
+ likes: [], |
|
35 |
+ show_likes: true, |
|
36 |
+ }, |
|
37 |
+ |
|
38 |
+ computed: { |
|
39 |
+ feed_visible() { |
|
40 |
+ return ( |
|
41 |
+ !this.show_likes && |
|
42 |
+ this.current_feed.metadata.title !== null && |
|
43 |
+ this.current_feed.items.length > 0 |
|
44 |
+ ); |
|
45 |
+ }, |
|
46 |
+ |
|
47 |
+ item_content() { |
|
48 |
+ let result = null; |
|
49 |
+ if (this.current_item.content !== null) { |
|
50 |
+ result = DOMPurify.sanitize(this.current_item.content, { |
|
51 |
+ FORBID_TAG: ["style"], |
|
52 |
+ FORBID_ATTR: ["style"], |
|
53 |
+ }); |
|
54 |
+ } |
|
55 |
+ return result; |
|
56 |
+ }, |
|
57 |
+ }, |
|
58 |
+ |
|
59 |
+ methods: { |
|
60 |
+ list_likes() { |
|
61 |
+ this.likes = []; |
|
62 |
+ oboe("events.json").node("*", (ev) => { |
|
63 |
+ let { event } = ev; |
|
64 |
+ if (event === "like-item") { |
|
65 |
+ this.likes.unshift(ev); |
|
66 |
+ } |
|
67 |
+ }); |
|
68 |
+ this.show_likes = !this.show_likes; |
|
54 | 69 |
}, |
55 | 70 |
|
56 |
- methods: { |
|
57 |
- list_likes() { |
|
58 |
- this.likes = [] |
|
59 |
- oboe('events.json') |
|
60 |
- .node('*', (ev) => { |
|
61 |
- let {event} = ev; |
|
62 |
- if (event === 'like-item') { |
|
63 |
- this.likes.push(ev); |
|
64 |
- } |
|
65 |
- }); |
|
66 |
- this.show_likes = !this.show_likes; |
|
67 |
- }, |
|
68 |
- |
|
69 |
- toggleCollapse() { |
|
70 |
- this.collapsed = !this.collapsed; |
|
71 |
- }, |
|
72 |
- |
|
73 |
- sanitize(html) { |
|
74 |
- return DOMPurify.sanitize(html, { |
|
75 |
- FORBID_TAG: ['style'], |
|
76 |
- FORBID_ATTR: ['style'], |
|
77 |
- }); |
|
78 |
- }, |
|
79 |
- |
|
80 |
- get_remote_feed: function (path) { |
|
81 |
- var promise = new Promise((resolve, reject) => { |
|
82 |
- window.fetch(path).then((resp) => resp.json()) |
|
83 |
- .then((data) => { |
|
84 |
- var result = Object.assign({}, data); |
|
85 |
- result.fetch_url = data['fetch-url']; |
|
86 |
- result.base_path = path; |
|
87 |
- window.history.pushState({ |
|
88 |
- 'current_feed': result |
|
89 |
- }, "", window.location.pathname); |
|
90 |
- resolve(result); |
|
91 |
- return promise; |
|
92 |
- }, reject.bind(promise)); |
|
93 |
- }); |
|
71 |
+ toggleCollapse() { |
|
72 |
+ this.collapsed = !this.collapsed; |
|
73 |
+ }, |
|
74 |
+ |
|
75 |
+ sanitize(html) { |
|
76 |
+ return DOMPurify.sanitize(html, { |
|
77 |
+ FORBID_TAG: ["style"], |
|
78 |
+ FORBID_ATTR: ["style"], |
|
79 |
+ }); |
|
80 |
+ }, |
|
81 |
+ |
|
82 |
+ get_remote_feed: function (path, shouldPushState = true) { |
|
83 |
+ var promise = new Promise((resolve, reject) => { |
|
84 |
+ window |
|
85 |
+ .fetch(path + "index.json") |
|
86 |
+ .then((resp) => resp.json()) |
|
87 |
+ .then((data) => { |
|
88 |
+ var result = Object.assign({}, data); |
|
89 |
+ result.fetch_url = data["fetch-url"]; |
|
90 |
+ result.base_path = path; |
|
91 |
+ if (shouldPushState) { |
|
92 |
+ window.history.pushState( |
|
93 |
+ { |
|
94 |
+ current_feed: result, |
|
95 |
+ }, |
|
96 |
+ "", |
|
97 |
+ window.location.pathname |
|
98 |
+ ); |
|
99 |
+ } |
|
100 |
+ resolve(result); |
|
94 | 101 |
return promise; |
95 |
- }, |
|
96 |
- |
|
97 |
- get_feed: function (path) { |
|
98 |
- this.get_remote_feed(path) |
|
99 |
- .then((result) => Vue.set(this, 'current_feed', result)) |
|
100 |
- .then(() => this.show_likes = false); |
|
101 |
- }, |
|
102 |
- |
|
103 |
- like(item, feed) { |
|
104 |
- fetch('https://<URL>/hub/feed_archive', { |
|
105 |
- method: 'POST', |
|
106 |
- body: JSON.stringify({ |
|
107 |
- 'event': 'like-item', |
|
108 |
- 'item': item.link, |
|
109 |
- 'title': item.title, |
|
110 |
- 'author': item.author, |
|
111 |
- 'feed-title': feed.metadata.title, |
|
112 |
- 'feed-link': feed.metadata.link, |
|
113 |
- }), |
|
114 |
- }); |
|
115 |
- }, |
|
116 |
- |
|
117 |
- get_item(path) { |
|
118 |
- window.fetch(this.current_feed.base_path + path).then((resp) => resp.json()) |
|
119 |
- .then((data) => { |
|
120 |
- fetch('https://<URL>/hub/feed_archive', { |
|
121 |
- method: 'POST', |
|
122 |
- body: JSON.stringify({ |
|
123 |
- 'event': 'read-item', |
|
124 |
- 'item': data.link, |
|
125 |
- 'title': data.title, |
|
126 |
- 'author': data.author, |
|
127 |
- 'feed-title': this.current_feed.metadata.title, |
|
128 |
- 'feed-link': this.current_feed.metadata.link, |
|
129 |
- }), |
|
130 |
- }); |
|
131 |
- window.history.pushState({ |
|
132 |
- 'current_feed': root.current_feed, |
|
133 |
- 'current_item': data |
|
134 |
- }, "", window.location.pathname); |
|
135 |
- Object.assign(this.current_item, data); |
|
136 |
- }); |
|
137 |
- }, |
|
138 |
- |
|
139 |
- has_items(feed) { |
|
140 |
- var count = this.feed_item_counts[feed.path]; |
|
141 |
- return count === undefined || (count > 0); |
|
142 |
- }, |
|
102 |
+ }, reject.bind(promise)); |
|
103 |
+ }); |
|
104 |
+ return promise; |
|
105 |
+ }, |
|
143 | 106 |
|
107 |
+ get_feed: function (path) { |
|
108 |
+ this.get_remote_feed(path) |
|
109 |
+ .then((result) => Vue.set(this, "current_feed", result)) |
|
110 |
+ .then(() => (this.show_likes = false)); |
|
144 | 111 |
}, |
145 | 112 |
|
146 |
- ready() { |
|
147 |
- oboe('events.json') |
|
148 |
- .node('*', (ev) => { |
|
149 |
- let {event} = ev; |
|
150 |
- if (event === 'like-item') { |
|
151 |
- this.likes.push(ev); |
|
152 |
- } |
|
153 |
- }); |
|
154 |
- |
|
155 |
- window.fetch(baseUrl+'/index.json').then((resp) => resp.json()) |
|
156 |
- .then(function (data) { |
|
157 |
- root.pull_time = data['pull-time']; |
|
158 |
- root.feed_urls = data['feed-urls']; |
|
159 |
- root.feeds = data.feeds; |
|
160 |
- return data; |
|
161 |
- }) |
|
162 |
- .then((data) => { |
|
163 |
- root.feeds.forEach((feed) => { |
|
164 |
- // console.log(feed); |
|
165 |
- this.get_remote_feed(feed.path) |
|
166 |
- .then((feed_index) => Vue.set(this.feed_item_counts, feed.path, feed_index.items.length)); |
|
167 |
- }); |
|
168 |
- }); |
|
113 |
+ like(item, feed) { |
|
114 |
+ fetch("https://srv2.elangley.org/hub/feed_archive", { |
|
115 |
+ method: "POST", |
|
116 |
+ body: JSON.stringify({ |
|
117 |
+ event: "like-item", |
|
118 |
+ item: item.link, |
|
119 |
+ title: item.title, |
|
120 |
+ author: item.author, |
|
121 |
+ "feed-title": feed.metadata.title, |
|
122 |
+ "feed-link": feed.metadata.link, |
|
123 |
+ }), |
|
124 |
+ }); |
|
125 |
+ }, |
|
169 | 126 |
|
127 |
+ get_item(path) { |
|
128 |
+ window |
|
129 |
+ .fetch(this.current_feed.base_path + path) |
|
130 |
+ .then((resp) => resp.json()) |
|
131 |
+ .then((data) => { |
|
132 |
+ fetch("https://srv2.elangley.org/hub/feed_archive", { |
|
133 |
+ method: "POST", |
|
134 |
+ body: JSON.stringify({ |
|
135 |
+ event: "read-item", |
|
136 |
+ item: data.link, |
|
137 |
+ title: data.title, |
|
138 |
+ author: data.author, |
|
139 |
+ "feed-title": this.current_feed.metadata.title, |
|
140 |
+ "feed-link": this.current_feed.metadata.link, |
|
141 |
+ }), |
|
142 |
+ }); |
|
143 |
+ window.history.pushState( |
|
144 |
+ { |
|
145 |
+ current_feed: root.current_feed, |
|
146 |
+ current_item: data, |
|
147 |
+ }, |
|
148 |
+ "", |
|
149 |
+ window.location.pathname |
|
150 |
+ ); |
|
151 |
+ Object.assign(this.current_item, data); |
|
152 |
+ this.current_item.path = path; |
|
153 |
+ }); |
|
170 | 154 |
}, |
171 | 155 |
|
156 |
+ has_items(feed) { |
|
157 |
+ var count = this.feed_item_counts[feed.path]; |
|
158 |
+ return count === undefined || count > 0; |
|
159 |
+ }, |
|
160 |
+ }, |
|
161 |
+ |
|
162 |
+ ready() { |
|
163 |
+ oboe("events.json").node("*", (ev) => { |
|
164 |
+ let { event } = ev; |
|
165 |
+ if (event === "like-item") { |
|
166 |
+ this.likes.unshift(ev); |
|
167 |
+ } |
|
168 |
+ }); |
|
169 |
+ |
|
170 |
+ window |
|
171 |
+ .fetch(baseUrl + "/index.json") |
|
172 |
+ .then((resp) => resp.json()) |
|
173 |
+ .then(function (data) { |
|
174 |
+ root.pull_time = data["pull-time"]; |
|
175 |
+ root.feed_urls = data["feed-urls"]; |
|
176 |
+ root.feeds = data.feeds; |
|
177 |
+ return data; |
|
178 |
+ }) |
|
179 |
+ .then((data) => { |
|
180 |
+ root.feeds.forEach((feed) => { |
|
181 |
+ // console.log(feed); |
|
182 |
+ this.get_remote_feed(feed.path, false).then((feed_index) => |
|
183 |
+ Vue.set(this.feed_item_counts, feed.path, feed_index.items.length) |
|
184 |
+ ); |
|
185 |
+ }); |
|
186 |
+ }); |
|
187 |
+ }, |
|
172 | 188 |
}); |
173 | 189 |
|
174 | 190 |
window.onpopstate = function (ev) { |
175 |
- // console.log(ev); |
|
176 |
- var current_feed = ev.state.current_feed, current_item = ev.state.current_item; |
|
191 |
+ // console.log(ev); |
|
192 |
+ var current_feed = ev.state.current_feed, |
|
193 |
+ current_item = ev.state.current_item; |
|
177 | 194 |
|
178 |
- Object.assign(root.current_feed, current_feed); |
|
195 |
+ Object.assign(root.current_feed, current_feed); |
|
179 | 196 |
|
180 |
- if (current_item !== undefined) { |
|
181 |
- Object.assign(root.current_item, current_item); |
|
182 |
- } |
|
197 |
+ if (current_item !== undefined) { |
|
198 |
+ Object.assign(root.current_item, current_item); |
|
199 |
+ } |
|
183 | 200 |
}; |
184 | 201 |
|
185 |
-document.addEventListener('DOMContentLoaded', function (ev) { |
|
186 |
- if (window.history.state !== null) { |
|
187 |
- Object.assign(root.current_feed, window.history.state.current_feed); |
|
188 |
- if (window.history.state.current_item !== undefined) { |
|
189 |
- Object.assign(root.current_item, window.history.state.current_item); |
|
190 |
- } |
|
202 |
+document.addEventListener("DOMContentLoaded", function (ev) { |
|
203 |
+ if (window.history.state !== null) { |
|
204 |
+ Object.assign(root.current_feed, window.history.state.current_feed); |
|
205 |
+ if (window.history.state.current_item !== undefined) { |
|
206 |
+ Object.assign(root.current_item, window.history.state.current_item); |
|
191 | 207 |
} |
208 |
+ } |
|
192 | 209 |
}); |