blob: 8c60064eac2e7f38617995555485bd4e8bbc0b20 [file] [log] [blame]
// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:cocoon_service/protos.dart' show Commit;
import 'commit_author_avatar.dart';
import 'progress_button.dart';
// TODO(ianh): Factor out the logic in task_overlay.dart and use it here as well,
// so that all our popups have the same look and feel and we don't duplicate code.
/// Displays Git commit information.
///
/// On click, it will open an [OverlayEntry] with [CommitOverlayContents]
/// to show the information provided. Otherwise, it just shows the avatar
/// for the author of this commit. Clicking outside of the [OverlayEntry]
/// will close it.
class CommitBox extends StatefulWidget {
const CommitBox({
Key key,
@required this.commit,
}) : assert(commit != null),
super(key: key);
/// The commit being shown
final Commit commit;
@override
_CommitBoxState createState() => _CommitBoxState();
}
class _CommitBoxState extends State<CommitBox> {
OverlayEntry _commitOverlay;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: _handleTap,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: CommitAuthorAvatar(commit: widget.commit),
),
);
}
void _handleTap() {
_commitOverlay = OverlayEntry(
builder: (_) => CommitOverlayContents(
parentContext: context,
commit: widget.commit,
closeCallback: _closeOverlay,
),
);
Overlay.of(context).insert(_commitOverlay);
}
void _closeOverlay() => _commitOverlay.remove();
}
/// Displays the information from a Git commit.
///
/// This is intended to be inserted in an [OverlayEntry] as it requires
/// [closeCallback] that will remove the widget from the tree.
class CommitOverlayContents extends StatelessWidget {
const CommitOverlayContents({
Key key,
@required this.parentContext,
@required this.commit,
@required this.closeCallback,
}) : assert(parentContext != null),
assert(commit != null),
assert(closeCallback != null),
super(key: key);
/// The parent context that has the size of the whole screen
final BuildContext parentContext;
/// The commit data to display in the overlay
final Commit commit;
/// This callback removes the parent overlay from the widget tree.
///
/// On a click that is outside the area of the overlay (the rest of the screen),
/// this callback is called closing the overlay.
final void Function() closeCallback;
@override
Widget build(BuildContext context) {
final RenderBox renderBox = parentContext.findRenderObject() as RenderBox;
final Offset offsetLeft = renderBox.localToGlobal(Offset.zero);
return Stack(
children: <Widget>[
// This is the area a user can click (the rest of the screen) to close the overlay.
GestureDetector(
onTap: closeCallback,
child: Container(
width: MediaQuery.of(parentContext).size.width,
height: MediaQuery.of(parentContext).size.height,
// Color must be defined otherwise the container can't be clicked on
color: Colors.transparent,
),
),
Positioned(
width: 300,
// Move this overlay to be where the parent is
top: offsetLeft.dy + (renderBox.size.height / 2),
left: offsetLeft.dx + (renderBox.size.width / 2),
child: Card(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
ListTile(
leading: CommitAuthorAvatar(commit: commit),
// TODO(chillers): Show commit message here instead: https://github.com/flutter/cocoon/issues/435
// Shorten the SHA as we only need first 7 digits to be able
// to lookup the commit.
title: SelectableText(commit.sha.substring(0, 7)),
subtitle: SelectableText(commit.author),
),
ButtonBar(
children: <Widget>[
ProgressButton(
child: const Text('OPEN GITHUB'),
onPressed: _openGithub,
),
],
),
],
),
),
),
],
);
}
Future<void> _openGithub() async {
final String githubUrl = 'https://github.com/${commit.repository}/commit/${commit.sha}';
await launch(githubUrl);
}
}