Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Commit 4c9f3b4

Browse files
feat: slides thumbnails on large screen (#1294)
* feat: slides thumbnails aside * feat: display thumbnails as of screen wider than 1200px * feat: deck selector and fix list of slides in popover * fix: spacing in fullscreen without thumbnails * feat: navigate to slide from aside * feat: no slide preview if thumbnails are displayed
1 parent d4125f2 commit 4c9f3b4

File tree

22 files changed

+406
-163
lines changed

22 files changed

+406
-163
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- highlight-code: v3.3.1 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/webcomponents/highlight-code/CHANGELOG.md))
88

9+
### Others
10+
11+
- - deck-utils: v4.1.0 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/utils/deck/CHANGELOG.md))
12+
913
<a name="4.8.0"></a>
1014

1115
# [4.8.0](https://github.com/deckgo/deckdeckgo/compare/v4.7.0...v4.8.0) (2021-06-13)

studio/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

studio/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@deckdeckgo/charts": "^2.1.0",
2424
"@deckdeckgo/color": "^4.1.0",
2525
"@deckdeckgo/core": "^8.2.1",
26-
"@deckdeckgo/deck-utils": "^4.0.2",
26+
"@deckdeckgo/deck-utils": "^4.1.0",
2727
"@deckdeckgo/demo": "^2.1.0",
2828
"@deckdeckgo/drag-resize-rotate": "^2.2.0",
2929
"@deckdeckgo/highlight-code": "^3.3.1",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
app-slides-aside {
2+
display: flex;
3+
flex-direction: column;
4+
5+
min-height: 100%;
6+
height: 100%;
7+
8+
width: var(--slides-aside-width);
9+
10+
padding: 16px;
11+
overflow: scroll;
12+
border-right: 1px solid #dedede;
13+
14+
--preview-width: calc(var(--slides-aside-width) - 32px);
15+
16+
app-slide-thumbnail {
17+
margin-bottom: 16px;
18+
}
19+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import {Component, Listen, h, Host, State, Prop} from '@stencil/core';
2+
3+
import {debounce} from '@deckdeckgo/utils';
4+
5+
import {isSlide} from '../../../../../../../utils/deck/src';
6+
import {deckSelector, slideTo} from '../../../../utils/editor/deck.utils';
7+
8+
@Component({
9+
tag: 'app-slides-aside',
10+
styleUrl: 'app-slides-aside.scss'
11+
})
12+
export class AppSlidesAside {
13+
@State()
14+
private slides: HTMLElement[] = [];
15+
16+
@Prop()
17+
deckRef!: HTMLDeckgoDeckElement;
18+
19+
private readonly debounceUpdateAllSlides: () => void;
20+
21+
private readonly debounceUpdateSlide: (updateSlide: HTMLElement) => void;
22+
23+
constructor() {
24+
this.debounceUpdateAllSlides = debounce(async () => {
25+
await this.updateAllSlides();
26+
}, 750);
27+
28+
this.debounceUpdateSlide = debounce(async (updateSlide: HTMLElement) => {
29+
await this.updateSlide(updateSlide);
30+
}, 750);
31+
}
32+
33+
componentDidLoad() {
34+
this.debounceUpdateAllSlides();
35+
}
36+
37+
@Listen('deckDidLoad', {target: 'document'})
38+
onDeckDidLoad() {
39+
this.debounceUpdateAllSlides();
40+
}
41+
42+
@Listen('deckDidChange', {target: 'document'})
43+
onDeckDidChange() {
44+
this.debounceUpdateAllSlides();
45+
}
46+
47+
@Listen('slideDidUpdate', {target: 'document'})
48+
onSlideDidUpdate({detail: updatedSlide}: CustomEvent<HTMLElement>) {
49+
this.debounceUpdateSlide(updatedSlide);
50+
}
51+
52+
private async updateSlide(updatedSlide: HTMLElement) {
53+
const slideIndex: number = Array.from(updatedSlide.parentNode.children).indexOf(updatedSlide);
54+
55+
this.slides = [...this.slides.map((slide: HTMLElement, index: number) => (slideIndex === index ? (updatedSlide.cloneNode(true) as HTMLElement) : slide))];
56+
}
57+
58+
private async updateAllSlides() {
59+
const slides: NodeListOf<HTMLElement> = document.querySelectorAll(`${deckSelector} > *`);
60+
61+
if (!slides) {
62+
return;
63+
}
64+
65+
this.slides = Array.from(slides)
66+
.filter((slide: HTMLElement) => isSlide(slide))
67+
.map((slide: HTMLElement) => slide.cloneNode(true) as HTMLElement);
68+
}
69+
70+
render() {
71+
return (
72+
<Host>
73+
{this.slides.map((slide: HTMLElement, index: number) => (
74+
<app-slide-thumbnail
75+
custom-tappable
76+
onClick={async () => await slideTo(index)}
77+
key={slide.getAttribute('slide_id')}
78+
slide={slide}
79+
deck={this.deckRef}></app-slide-thumbnail>
80+
))}
81+
</Host>
82+
);
83+
}
84+
}

studio/src/app/components/editor/actions/deck/app-actions-deck/app-actions-deck.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {MoreAction} from '../../../../../types/editor/more-action';
1515

1616
import {BackupOfflineService} from '../../../../../services/editor/backup/backup.offline.service';
1717

18-
import { AppIcon } from '../../../../core/app-icon/app-icon';
18+
import {AppIcon} from '../../../../core/app-icon/app-icon';
1919

2020
@Component({
2121
tag: 'app-actions-deck',
@@ -42,9 +42,6 @@ export class AppActionsDeck {
4242
@Prop()
4343
animatePrevNextSlide: EventEmitter;
4444

45-
@Prop()
46-
slideTo: EventEmitter;
47-
4845
@Prop()
4946
toggleFullScreen: EventEmitter;
5047

@@ -83,12 +80,6 @@ export class AppActionsDeck {
8380
cssClass: 'popover-menu popover-menu-wide'
8481
});
8582

86-
popover.onDidDismiss().then(async (detail: OverlayEventDetail) => {
87-
if (detail.data >= 0) {
88-
this.slideTo.emit(detail.data);
89-
}
90-
});
91-
9283
await popover.present();
9384
}
9485

studio/src/app/components/editor/actions/footer/app-actions-editor/app-actions-editor.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ export class AppActionsEditor {
3535

3636
@Event() private animatePrevNextSlide: EventEmitter<boolean>;
3737

38-
@Event() private slideTo: EventEmitter<number>;
39-
4038
@Event() private toggleFullScreen: EventEmitter<void>;
4139

4240
@Event() private actionPublish: EventEmitter<void>;
@@ -214,7 +212,6 @@ export class AppActionsEditor {
214212
signIn={this.signIn}
215213
addSlide={this.addSlide}
216214
animatePrevNextSlide={this.animatePrevNextSlide}
217-
slideTo={this.slideTo}
218215
toggleFullScreen={this.toggleFullScreen}
219216
actionPublish={this.actionPublish}
220217
deckDidChange={this.deckDidChange}
Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
@use "../../../../../global/theme/mixins/editor";
2-
@use "../../../../../global/theme/mixins/deck";
3-
41
app-slide-preview {
52
position: absolute;
63
top: var(--ios-top, 8px);
@@ -19,25 +16,4 @@ app-slide-preview {
1916
visibility: hidden;
2017
opacity: 0;
2118
}
22-
23-
article {
24-
position: relative;
25-
26-
--preview-width: 200px;
27-
28-
width: var(--preview-width);
29-
height: calc(var(--preview-width) * 9 / 16);
30-
31-
@media screen and (max-width: 768px) {
32-
--preview-width: 128px;
33-
}
34-
35-
overflow: hidden;
36-
37-
@include editor.panel;
38-
39-
deckgo-deck {
40-
@include deck.padding;
41-
}
42-
}
4319
}

studio/src/app/components/editor/slide/app-slide-preview/app-slide-preview.tsx

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Component, h, Host, Listen, State, Event, EventEmitter, Element, Prop} from '@stencil/core';
22

3-
import {cleanContent, isSlide} from '@deckdeckgo/deck-utils';
3+
import {isSlide} from '@deckdeckgo/deck-utils';
44
import {debounce, isIOS, isLandscape} from '@deckdeckgo/utils';
55

66
import {SlotUtils} from '../../../../utils/editor/slot.utils';
@@ -21,7 +21,8 @@ export class AppSlidePreview {
2121
@State()
2222
private iosPositionTop: string | undefined = undefined;
2323

24-
private deckPreviewRef!: HTMLDeckgoDeckElement;
24+
@State()
25+
private slideElement: HTMLElement | undefined = undefined;
2526

2627
@Event({bubbles: false}) private previewAttached: EventEmitter<void>;
2728

@@ -67,8 +68,6 @@ export class AppSlidePreview {
6768
this.preview = isSlide(selectedElement?.parentElement) && SlotUtils.isNodeEditable(selectedElement) && !SlotUtils.isNodeWordCloud(selectedElement);
6869

6970
if (this.preview) {
70-
await this.initDeckPreview();
71-
7271
this.el.addEventListener('previewAttached', async () => await this.updateSlide(selectedElement.parentElement), {once: true});
7372

7473
this.deckRef.addEventListener('keypress', () => this.debounceUpdatePreview(), {passive: true});
@@ -85,28 +84,8 @@ export class AppSlidePreview {
8584
}
8685
}
8786

88-
async initDeckPreview() {
89-
if (!this.deckRef) {
90-
return;
91-
}
92-
93-
this.deckPreviewRef?.setAttribute('style', this.deckRef.style.cssText);
94-
95-
await this.deckPreviewRef?.initSlideSize();
96-
}
97-
98-
async updateSlide(slide: HTMLElement | undefined) {
99-
if (!slide || !this.deckPreviewRef) {
100-
return;
101-
}
102-
103-
const content: string = await cleanContent(slide.outerHTML);
104-
105-
this.deckPreviewRef.innerHTML = content;
106-
}
107-
108-
private async blockSlide() {
109-
await this.deckPreviewRef?.blockSlide(true);
87+
private async updateSlide(slide: HTMLElement | undefined) {
88+
this.slideElement = slide?.cloneNode(true) as HTMLElement | undefined;
11089
}
11190

11291
private async updatePreview() {
@@ -130,7 +109,7 @@ export class AppSlidePreview {
130109
class={{
131110
preview: this.preview
132111
}}>
133-
<article>{this.renderPreview()}</article>
112+
{this.renderPreview()}
134113
</Host>
135114
);
136115
}
@@ -140,12 +119,6 @@ export class AppSlidePreview {
140119
return undefined;
141120
}
142121

143-
return (
144-
<deckgo-deck
145-
embedded={true}
146-
keyboard={false}
147-
ref={(el) => (this.deckPreviewRef = el as HTMLDeckgoDeckElement)}
148-
onSlidesDidLoad={() => this.blockSlide()}></deckgo-deck>
149-
);
122+
return <app-slide-thumbnail slide={this.slideElement} deck={this.deckRef}></app-slide-thumbnail>;
150123
}
151124
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
@use "../../../../../global/theme/mixins/editor";
2+
@use "../../../../../global/theme/mixins/deck";
3+
4+
app-slide-thumbnail {
5+
display: block;
6+
7+
position: relative;
8+
9+
width: var(--preview-width, 200px);
10+
height: calc(var(--preview-width, 200px) * 9 / 16);
11+
min-height: calc(var(--preview-width, 200px) * 9 / 16);
12+
13+
@media screen and (max-width: 768px) {
14+
--preview-width: 128px;
15+
}
16+
17+
overflow: hidden;
18+
19+
@include editor.panel;
20+
21+
deckgo-deck {
22+
pointer-events: none;
23+
24+
@include deck.padding;
25+
}
26+
}

0 commit comments

Comments
 (0)