Skip to content

Commit 82abc66

Browse files
committed
feat(comment-minimap): display scroll bar
1 parent fca05b7 commit 82abc66

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

src/Electron/Component/WebViewComponentInjection/highlight-and-scroll.ts

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// @ts-ignore
33
const prevReadAt = _prevReadAt_;
44
const highlightCommentEls: HTMLElement[] = [];
5-
const highlightCommentMarkMap: Map<HTMLElement, HTMLElement> = new Map();
65

76
exec();
87

@@ -144,33 +143,45 @@
144143
function addHighlightIndicator() {
145144
if (!highlightCommentEls.length) return;
146145

147-
// https://blog.jxck.io/entries/2016-06-25/intersection-observer.html#intersection-observer
148-
const observer = new IntersectionObserver((changes) => {
149-
for (let change of changes) {
150-
if (change.isIntersecting) {
151-
const mark = highlightCommentMarkMap.get(change.target as HTMLElement);
152-
if (mark) mark.classList.add('highlight-indicator-mark-done');
153-
}
154-
}
155-
}, {threshold: [0], rootMargin: '-40px'});
156-
157-
// create indicator
146+
// create indicator wrap
158147
const indicatorWrapEl = document.createElement('div');
159148
indicatorWrapEl.classList.add('highlight-indicator-wrap');
160149
document.body.appendChild(indicatorWrapEl);
161150

151+
// create indicator
162152
const indicatorEl = document.createElement('div');
163153
indicatorEl.classList.add('highlight-indicator');
164154
indicatorWrapEl.appendChild(indicatorEl);
165155

166-
const rect = document.querySelector('.js-discussion').getBoundingClientRect();
167-
const timelineHeight = rect.height;
168-
const timelineOffset = rect.top + window.pageYOffset; //.js-discussionのheightを使うために、commentの絶対位置をオフセットする必要がある
156+
// create current-pos
157+
const currentPosEl = document.createElement('div') ;
158+
currentPosEl.classList.add('highlight-indicator-scroll-current-pos');
159+
currentPosEl.style.opacity = '0';
160+
indicatorEl.appendChild(currentPosEl);
161+
162+
// calc timeline height
163+
const lastCommentBottom = getComments().pop().getBoundingClientRect().bottom;
164+
const timelineRect = document.querySelector('.js-discussion').getBoundingClientRect();
165+
const timelineHeight = timelineRect.height - (timelineRect.bottom - lastCommentBottom);
166+
const timelineOffset = timelineRect.top + window.pageYOffset; //.js-discussionのheightを使うために、commentの絶対位置をオフセットする必要がある
169167

170168
// タイムラインの高さが小さいときは、インジケータも小さくする
171169
const indicatorHeight = Math.min(timelineHeight / window.innerHeight, 1);
172170
indicatorEl.style.height = `${indicatorHeight * 100}%`;
173171

172+
// コメントが画面に表示されたときにmarkを非表示にする
173+
// https://blog.jxck.io/entries/2016-06-25/intersection-observer.html#intersection-observer
174+
const highlightCommentMarkMap: Map<HTMLElement, HTMLElement> = new Map();
175+
const observer = new IntersectionObserver((changes) => {
176+
for (let change of changes) {
177+
if (change.isIntersecting) {
178+
const mark = highlightCommentMarkMap.get(change.target as HTMLElement);
179+
if (mark) mark.classList.add('highlight-indicator-mark-done');
180+
}
181+
}
182+
}, {threshold: [0], rootMargin: '-40px'});
183+
184+
// create mark
174185
for (const comment of highlightCommentEls) {
175186
// calc mark position
176187
const commentRect = comment.getBoundingClientRect();
@@ -184,10 +195,11 @@
184195
const height = absHeight / timelineHeight * 100;
185196

186197
// create mark
187-
const markOffset = (50 - y) / 50 * 10; // markの位置がindicatorの上下ぴったりに来ないように、「中央(50%)を原点として、そこからの距離で0~10のオフセット」をつける
198+
// const markOffset = (50 - y) / 50 * 10; // markの位置がindicatorの上下ぴったりに来ないように、「中央(50%)を原点として、そこからの距離で0~10のオフセット」をつける
188199
const mark = document.createElement('div');
189200
mark.classList.add('highlight-indicator-mark');
190-
mark.style.top = `calc(${y}% + ${markOffset}px)`;
201+
// mark.style.top = `calc(${y}% + ${markOffset}px)`;
202+
mark.style.top = `${y}%`;
191203
mark.style.height = `${height}%`;
192204
indicatorEl.appendChild(mark);
193205

@@ -202,6 +214,32 @@
202214
// recursiveMarkDone(mark, marks);
203215
});
204216
}
217+
218+
// scroll position
219+
if (timelineRect.bottom > window.innerHeight) {
220+
window.addEventListener('wheel', async () => {
221+
const top = Math.max(0, window.scrollY - timelineRect.top);
222+
const bottom = Math.min(timelineHeight, (window.scrollY + window.innerHeight) - timelineRect.top);
223+
const height = (bottom - top) / timelineHeight;
224+
// if (Math.ceil(100 * height) >= 100) return;
225+
226+
currentPosEl.style.top = `${top/timelineHeight * 100}%`;
227+
currentPosEl.style.height = `${height * 100}%`;
228+
currentPosEl.style.opacity = null;
229+
currentPosEl.style.display = null;
230+
currentPosEl.style.transition = null;
231+
currentPosEl.ontransitionend = null;
232+
233+
const t = Date.now().toString();
234+
currentPosEl.dataset['time'] = t;
235+
await sleep(300);
236+
if (currentPosEl.dataset['time'] === t) {
237+
currentPosEl.style.opacity = '0';
238+
currentPosEl.style.transition = 'opacity 0.2s';
239+
currentPosEl.ontransitionend = () => currentPosEl.style.display = 'none';
240+
}
241+
});
242+
}
205243
}
206244

207245
// function recursiveMarkDone(doneMark: HTMLElement, marks: HTMLElement[]) {

src/Electron/Component/WebViewComponentInjection/style.css

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,18 @@
147147
/*border: solid 1px #1f9c35;*/
148148
border: solid 1px #EAECEF;
149149
box-sizing: border-box;
150-
border-radius: 2px;
150+
border-radius: 5px;
151+
}
152+
153+
.highlight-indicator-scroll-current-pos {
154+
position: absolute;
155+
top: 0;
156+
left: 0;
157+
width: 10px;
158+
height: 10px;
159+
border-radius: 5px;
160+
background: rgba(0, 0, 0, 0.3);
161+
z-index: 9999;
151162
}
152163

153164
.highlight-indicator-mark-done {

0 commit comments

Comments
 (0)