Skip to content

Commit

Permalink
Fix the next/prev buttons when some events have no screenshot (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
passsy authored Jan 3, 2025
1 parent ed49343 commit b93cfad
Show file tree
Hide file tree
Showing 7 changed files with 3,199 additions and 3,021 deletions.
154 changes: 110 additions & 44 deletions lib/src/timeline/html/components/modal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' if (dart.library.io) '../web/web_stubs.dart';

import 'package:dartx/dartx.dart';
import 'package:jaspr/jaspr.dart';
import 'package:spot/src/timeline/html/web/theme.dart';

import 'package:spot/src/timeline/html/web/timeline_event.dart';

/// A modal to show a single event in detail.
Expand Down Expand Up @@ -58,15 +58,33 @@ class ModalState extends State<Modal> {

void showPrev() {
if (_index == null) return;
final lastScreenshot =
component.events.lastOrNullWhere((e) => e.screenshotUrl != null);
final prevWithScreenshot = component.events
.take(_index!)
.reversed
.firstOrNullWhere((e) => e.screenshotUrl != null) ??
lastScreenshot;
if (prevWithScreenshot == null) return;
final nextIndex = component.events.indexOf(prevWithScreenshot);

setState(() {
_index = (_index! - 1) % component.events.length;
_index = nextIndex;
});
}

void showNext() {
if (_index == null) return;
final firstWithScreenshot =
component.events.firstOrNullWhere((e) => e.screenshotUrl != null);
final nextWithScreenshot = component.events
.skip(_index! + 1)
.firstOrNullWhere((e) => e.screenshotUrl != null) ??
firstWithScreenshot;
if (nextWithScreenshot == null) return;
final nextIndex = component.events.indexOf(nextWithScreenshot);
setState(() {
_index = (_index! + 1) % component.events.length;
_index = nextIndex;
});
}

Expand All @@ -78,43 +96,61 @@ class ModalState extends State<Modal> {
classes: "modal ${_index != null ? 'show' : ''}",
events: events(onClick: close),
[
span(
classes: "close",
events: events(onClick: close),
[raw("&times;")],
),
div(classes: "modal-content", [
div(styles: const Styles().raw({'width': '100%'}), []),
img(
alt: "Screenshot of the Event",
src: event?.screenshotUrl ?? "",
events: {
'click': (dynamic e) {
e.stopPropagation();
},
},
),
div(classes: "caption", [
a(
classes: "nav nav-left",
events: {
'click': (dynamic e) {
e.preventDefault();
e.stopPropagation();
showPrev();
},
span(
classes: "close",
events: events(onClick: close),
[raw("&times;")],
),
a(
classes: "nav nav-left",
events: {
'click': (dynamic e) {
e.preventDefault();
e.stopPropagation();
showPrev();
},
href: "",
[raw("&#10094;")],
),
div([text(event?.eventType ?? '')]),
a(
classes: "nav nav-right",
events: {
'click': (dynamic e) {
e.preventDefault();
e.stopPropagation();
showNext();
},
},
href: "",
[raw("&#10094;")],
),
a(
classes: "nav nav-right",
events: {
'click': (dynamic e) {
e.preventDefault();
e.stopPropagation();
showNext();
},
href: "",
[raw("&#10095;")],
),
},
href: "",
[raw("&#10095;")],
),
]),
div(classes: "sidebar", [
div(styles: const Styles().box(height: 10.px), []),
h3([text(event?.eventType ?? '')]),
p([text(event?.timestamp ?? '')]),
p(events: {
'click': (dynamic e) {
e.stopPropagation();
},
}, [
a(href: event?.jetBrainsLink ?? '', [
text(event?.caller ?? ''),
]),
]),
p([text(event?.details ?? '')]),
]),
],
);
Expand All @@ -136,27 +172,38 @@ class ModalState extends State<Modal> {
)
.background(color: modalBackgroundColor)
.raw({'z-index': '1'}),
css('&.show').box(display: Display.block),
css('img').box(maxWidth: 100.percent, height: Unit.auto),
css('&.show').box(display: Display.flex),
css('img')
.box(width: 100.percent, height: 100.percent)
.raw({'object-fit': 'contain'}) //
.raw({'margin': 'auto'}),
css('span').background(color: Colors.transparent),
css('.modal-content')
.box(
margin: const EdgeInsets.all(Unit.auto),
display: Display.flex,
maxWidth: 80.percent,
height: Unit.auto,
maxWidth: 100.percent,
height: 100.vh,
overflow: Overflow.hidden,
border: const Border.all(BorderSide.none()),
position: const Position.relative(),
)
.flexbox(direction: FlexDirection.column)
.raw({'flex': '1'}) //
.background(color: Colors.transparent),
css('.close', [
css('&') //
css('&')
.box(position: Position.absolute(top: 15.px, right: 35.px))
.text(
color: closeColor,
fontSize: closeFontSize,
fontWeight: FontWeight.bold,
shadow: TextShadow(
color: const Color.hex('#00000080'),
offsetX: 0.px,
offsetY: 2.px,
blur: 8.px,
),
),
css('&:hover, &:focus') //
.box(cursor: Cursor.pointer)
Expand All @@ -175,20 +222,39 @@ class ModalState extends State<Modal> {
.text(
color: navColor,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
fontSize: navFontSize,
shadow: TextShadow(
color: const Color.hex('#00000080'),
offsetX: 0.px,
offsetY: 2.px,
blur: 8.px,
),
)
.background(color: navBackgroundColor)
.raw({'user-select': 'none'}),
css('&:hover').text(color: navHoverColor),
css('&.nav-left').box(position: Position.absolute(left: (-50).px)),
css('&.nav-right')
.box(position: Position.absolute(right: (-50).px)),
css('&.nav-left').box(position: Position.absolute(left: 30.px)),
css('&.nav-right').box(position: Position.absolute(right: 30.px)),
]),
css('.caption', [
css('.sidebar', [
css('&')
.box(padding: captionPadding, height: 150.px)
.text(color: captionColor, align: TextAlign.center)
.background(color: Colors.transparent),
.box(
width: 400.px,
height: 100.percent,
overflow: Overflow.hidden,
padding: EdgeInsets.symmetric(horizontal: 16.px),
shadow: BoxShadow(
color: const Color.hex('#00000080'),
offsetX: 0.px,
offsetY: 0.px,
blur: 3.px,
),
)
.text(color: captionColor, align: TextAlign.start)
.raw({'line-break': 'anywhere'}) //
.background(color: Colors.white),
css('& a').text(decoration: TextDecoration.none),
css('& div').background(color: Colors.transparent),
]),
]),
Expand Down
Loading

0 comments on commit b93cfad

Please sign in to comment.