Use flutter_simple_treeview (#461)

pull/470/head
Brett Morgan 5 years ago committed by GitHub
parent 2c6f2ddb1f
commit 47b8610ed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,9 +4,10 @@
import 'dart:io';
import 'package:file_chooser/file_chooser.dart' as file_chooser;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:file_chooser/file_chooser.dart' as file_chooser;
import 'package:flutter_simple_treeview/flutter_simple_treeview.dart';
import 'package:logging/logging.dart';
import 'package:menubar/menubar.dart' as menubar;
import 'package:meta/meta.dart';
@ -14,7 +15,6 @@ import 'package:provider/provider.dart';
import 'src/model/photo_search_model.dart';
import 'src/unsplash/unsplash.dart';
import 'src/widgets/data_tree.dart';
import 'src/widgets/photo_details.dart';
import 'src/widgets/photo_search_dialog.dart';
import 'src/widgets/split.dart';
@ -86,7 +86,16 @@ class UnsplashHomePage extends StatelessWidget {
? Split(
axis: Axis.horizontal,
initialFirstFraction: 0.4,
firstChild: DataTree(photoSearchModel.entries),
firstChild: Scrollbar(
child: SingleChildScrollView(
child: TreeView(
nodes: photoSearchModel.entries
.map(_buildSearchEntry)
.toList(),
indent: 0,
),
),
),
secondChild: Center(
child: photoSearchModel.selectedPhoto != null
? PhotoDetails(
@ -124,4 +133,31 @@ class UnsplashHomePage extends StatelessWidget {
),
);
}
TreeNode _buildSearchEntry(SearchEntry searchEntry) {
return TreeNode(
content: Expanded(
child: Text(searchEntry.query),
),
children: searchEntry.photos
.map<TreeNode>(
(photo) => TreeNode(
content: Expanded(
child: InkWell(
onTap: () {
searchEntry.model.selectedPhoto = photo;
},
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
'Photo by ${photo.user.name}',
),
),
),
),
),
)
.toList(),
);
}
}

@ -9,43 +9,24 @@ import 'package:meta/meta.dart';
import '../unsplash/photo.dart';
import '../unsplash/unsplash.dart';
import '../widgets/data_tree.dart' show Entry;
import 'search.dart';
class _PhotoEntry extends Entry {
_PhotoEntry(this._photo, this._model) : super('Photo by ${_photo.user.name}');
final Photo _photo;
final PhotoSearchModel _model;
@override
bool get isSelected => false;
@override
set isSelected(bool selected) {
_model._setSelectedPhoto(_photo);
}
}
class _SearchEntry extends Entry {
_SearchEntry(String query, List<Photo> photos, PhotoSearchModel model)
: super(
query,
List<Entry>.unmodifiable(
photos.map<Entry>((photo) => _PhotoEntry(photo, model)),
),
);
class SearchEntry {
const SearchEntry(this.query, this.photos, this.model);
final String query;
final List<Photo> photos;
final PhotoSearchModel model;
}
class PhotoSearchModel extends ChangeNotifier {
PhotoSearchModel(this._client);
final Unsplash _client;
List<Entry> get entries => List.unmodifiable(_entries);
final List<Entry> _entries = <Entry>[];
List<SearchEntry> get entries => List.unmodifiable(_entries);
final List<SearchEntry> _entries = [];
Photo get selectedPhoto => _selectedPhoto;
void _setSelectedPhoto(Photo photo) {
set selectedPhoto(Photo photo) {
_selectedPhoto = photo;
notifyListeners();
}
@ -63,7 +44,7 @@ class PhotoSearchModel extends ChangeNotifier {
..results.addAll(result.results);
});
_entries.add(_SearchEntry(query, search.results.toList(), this));
_entries.add(SearchEntry(query, search.results.toList(), this));
notifyListeners();
}

@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:built_collection/built_collection.dart';
import 'model/search.dart';
import 'unsplash/api_error.dart';

@ -1,350 +0,0 @@
// Copyright 2019 The Flutter team. 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:flutter/scheduler.dart';
class DataTreeRule extends StatelessWidget {
const DataTreeRule({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 2,
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.1),
);
}
}
class DataTreeInkWell extends StatefulWidget {
const DataTreeInkWell({Key key, this.onTap, this.isSelected, this.child})
: super(key: key);
final VoidCallback onTap;
final bool isSelected;
final Widget child;
@override
_DataTreeInkWellState createState() => _DataTreeInkWellState();
}
class _DataTreeInkWellState extends State<DataTreeInkWell>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation selectionColor;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 100), vsync: this);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
void didUpdateWidget(DataTreeInkWell oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isSelected) {
controller.forward();
} else {
controller.reverse();
}
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final backgroundColor = controller
.drive(CurveTween(curve: Curves.fastOutSlowIn))
.drive(ColorTween(
begin: colorScheme.primary.withOpacity(0.0),
end: colorScheme.primary.withOpacity(0.08),
));
final iconColor = controller
.drive(CurveTween(curve: Curves.fastOutSlowIn))
.drive(ColorTween(
begin: colorScheme.onBackground.withOpacity(0.54),
end: colorScheme.onBackground.withOpacity(0.87),
));
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
return IconTheme(
data: IconThemeData(color: iconColor.value),
child: Container(
color: backgroundColor.value,
child: child,
),
);
},
child: InkWell(
onTap: widget.onTap,
splashFactory: InkRipple.splashFactory,
splashColor: colorScheme.primary.withOpacity(0.14),
highlightColor: Colors.transparent,
child: widget.child,
),
);
}
}
class DataTreeNode extends StatefulWidget {
const DataTreeNode({
Key key,
this.leading,
@required this.title,
this.backgroundColor,
this.onExpansionChanged,
this.onSelectionChanged,
this.children = const <Widget>[],
this.initiallyExpanded = false,
this.indent = 0,
this.height = 36,
}) : assert(initiallyExpanded != null),
assert(indent != null && indent >= 0),
super(key: key);
final Widget leading;
final Widget title;
final ValueChanged<bool> onExpansionChanged;
final ValueChanged<bool> onSelectionChanged;
final List<Widget> children;
final Color backgroundColor;
final bool initiallyExpanded;
final double indent;
final double height;
@override
_DataTreeNodeState createState() => _DataTreeNodeState();
}
class _DataTreeNodeState extends State<DataTreeNode>
with SingleTickerProviderStateMixin {
static final Animatable<double> _easeInTween =
CurveTween(curve: Curves.easeIn);
static final Animatable<double> _halfTween =
Tween<double>(begin: 0.0, end: 0.25);
AnimationController _controller;
Animation<double> _iconTurns;
Animation<double> _heightFactor;
bool _isExpanded = false;
bool _isSelected = false;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 200), vsync: this);
_heightFactor = _controller.drive(_easeInTween);
_iconTurns = _controller.drive(_halfTween.chain(_easeInTween));
_isExpanded = (PageStorage.of(context)?.readState(context) ??
widget.initiallyExpanded) as bool;
if (_isExpanded) {
_controller.value = 1.0;
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _handleNodeTap() {
setState(() {
_isExpanded = !_isExpanded;
if (_isExpanded) {
_controller.forward();
} else {
_controller.reverse().then<void>((value) {
if (!mounted) {
return;
}
setState(() {
// Rebuild without widget.children.
});
});
}
PageStorage.of(context)?.writeState(context, _isExpanded);
});
if (widget.onExpansionChanged != null) {
widget.onExpansionChanged(_isExpanded);
}
}
void _handleLeafTap() {
_isSelected = !_isSelected;
if (widget.onSelectionChanged != null) {
widget.onSelectionChanged(_isSelected);
}
}
Widget _buildChildren(BuildContext context, Widget child) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DataTreeInkWell(
onTap: _handleNodeTap,
isSelected: _isExpanded,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: widget.indent),
RotationTransition(
turns: _iconTurns,
child: Icon(
Icons.arrow_right,
size: 20,
),
),
const SizedBox(width: 8),
Icon(
Icons.folder,
size: 20,
),
const SizedBox(width: 16),
widget.title,
],
),
),
if (child != null) // If child == null, then this DataNode is closed.
const DataTreeRule(),
if (child != null)
ClipRect(
child: Align(
alignment: Alignment.topLeft,
heightFactor: _heightFactor.value,
child: child,
),
),
],
);
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final textColor = colorScheme.onBackground.withOpacity(0.87);
final closed = !_isExpanded && _controller.isDismissed;
return widget.children.isEmpty
// Leaf node.
? DataTreeInkWell(
onTap: _handleLeafTap,
isSelected: _isSelected,
child: Row(
children: <Widget>[
SizedBox(width: widget.indent),
Icon(
Icons.web_asset,
size: 20,
),
const SizedBox(width: 16),
DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2.copyWith(
color: textColor,
),
child: widget.title,
),
],
),
)
// Not a leaf node.
: AnimatedBuilder(
animation: _controller.view,
builder: _buildChildren,
child: closed
? null
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
for (int index = 0;
index < (widget.children.length * 2) - 1;
index += 1)
(index % 2 == 1)
? const DataTreeRule()
: widget.children[index ~/ 2],
],
),
);
}
}
// One entry in the multilevel list displayed by this app.
class Entry {
Entry(this.title, [this.children = const <Entry>[]]);
final String title;
final List<Entry> children;
bool isSelected = false;
bool isEnabled = true;
}
// A visualization of one Entry based on DataTreeNode.
class EntryItem extends StatefulWidget {
const EntryItem({Key key, this.entry}) : super(key: key);
final Entry entry;
@override
_EntryItemState createState() => _EntryItemState();
}
class _EntryItemState extends State<EntryItem> {
Widget _buildNodes(Entry root, double indent) {
return DataTreeNode(
key: PageStorageKey<Entry>(root),
onSelectionChanged: (isSelected) {
setState(() {
root.isSelected = isSelected;
});
},
title: Container(
alignment: AlignmentDirectional.centerStart,
height: 36,
child: Text(root.title),
),
indent: indent,
children: root.children.map<Widget>((entry) {
return _buildNodes(entry, indent + 28);
}).toList(),
);
}
@override
Widget build(BuildContext context) {
return _buildNodes(widget.entry, 16);
}
}
class DataTree extends StatelessWidget {
DataTree(this.entries)
: assert(entries != null),
assert(entries.isNotEmpty);
final List<Entry> entries;
@override
Widget build(BuildContext context) => ListView.builder(
itemCount: entries.length * 2 - 1,
itemBuilder: (context, index) {
if (index % 2 == 1) {
return const DataTreeRule();
}
return EntryItem(
entry: entries[index ~/ 2],
);
},
);
}

@ -29,96 +29,101 @@ class PhotoDetails extends StatefulWidget {
}
class _PhotoDetailsState extends State<PhotoDetails>
with SingleTickerProviderStateMixin {
with TickerProviderStateMixin {
Widget _buildPhotoAttribution(BuildContext context) {
return RichText(
text: TextSpan(
style: Theme.of(context).textTheme.bodyText2,
children: [
const TextSpan(text: 'Photo by '),
TextSpan(
text: widget.photo.user.name,
style: const TextStyle(
decoration: TextDecoration.underline,
return Expanded(
child: RichText(
overflow: TextOverflow.fade,
text: TextSpan(
style: Theme.of(context).textTheme.bodyText2,
children: [
const TextSpan(text: 'Photo by '),
TextSpan(
text: widget.photo.user.name,
style: const TextStyle(
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () async {
final url = Uri.encodeFull(
'https://unsplash.com/@${widget.photo.user.username}?utm_source=$unsplashAppName&utm_medium=referral');
if (await url_launcher.canLaunch(url)) {
await url_launcher.launch(url);
}
},
),
recognizer: TapGestureRecognizer()
..onTap = () async {
final url = Uri.encodeFull(
'https://unsplash.com/@${widget.photo.user.username}?utm_source=$unsplashAppName&utm_medium=referral');
if (await url_launcher.canLaunch(url)) {
await url_launcher.launch(url);
}
},
),
const TextSpan(text: ' on '),
TextSpan(
text: 'Unsplash',
style: const TextStyle(
decoration: TextDecoration.underline,
const TextSpan(text: ' on '),
TextSpan(
text: 'Unsplash',
style: const TextStyle(
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () async {
if (await url_launcher.canLaunch(_unsplashHomepage)) {
await url_launcher.launch(_unsplashHomepage);
}
},
),
recognizer: TapGestureRecognizer()
..onTap = () async {
if (await url_launcher.canLaunch(_unsplashHomepage)) {
await url_launcher.launch(_unsplashHomepage);
}
},
),
],
],
),
),
);
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 16),
Card(
shape: ContinuousRectangleBorder(
side: BorderSide(color: Colors.black12),
borderRadius: BorderRadius.circular(4),
),
child: AnimatedSize(
vsync: this,
duration: Duration(milliseconds: 750),
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 40),
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 400,
minHeight: 400,
),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: widget.photo.urls.small,
return Scrollbar(
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 16),
Card(
shape: ContinuousRectangleBorder(
side: BorderSide(color: Colors.black12),
borderRadius: BorderRadius.circular(4),
),
child: AnimatedSize(
vsync: this,
duration: Duration(milliseconds: 750),
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 40),
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 400,
minHeight: 400,
),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: widget.photo.urls.small,
),
),
),
),
),
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.only(left: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildPhotoAttribution(context),
const SizedBox(width: 8),
IconButton(
visualDensity: VisualDensity.compact,
icon: Icon(Icons.cloud_download),
onPressed: () => widget.onPhotoSave(widget.photo),
),
],
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.only(left: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildPhotoAttribution(context),
const SizedBox(width: 8),
IconButton(
visualDensity: VisualDensity.compact,
icon: Icon(Icons.cloud_download),
onPressed: () => widget.onPhotoSave(widget.photo),
),
],
),
),
),
const SizedBox(height: 48),
],
const SizedBox(height: 48),
],
),
),
),
);

@ -32,8 +32,8 @@ SPEC CHECKSUMS:
FlutterMacOS: 15bea8a44d2fa024068daa0140371c020b4b6ff9
menubar: 4e3d461d62d775540277ce6639acafe2a111a231
url_launcher: af78307ef9bafff91273b34f1c6c0c86a0004fd7
url_launcher_macos: 76867a28e24e0b6b98bfd65f157b64108e6d477a
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4
PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7
COCOAPODS: 1.8.4
COCOAPODS: 1.9.1

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/stuartmorgan/src/embedder-opensource/flutter-desktop-embedding/example/macos/Runner.xcodeproj">
</FileRef>
</Workspace>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
LastUpgradeVersion = "1150"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

@ -7,7 +7,7 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "4.0.0"
analysis_server_lib:
dependency: transitive
description:
@ -21,14 +21,7 @@ packages:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.39.8"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
version: "0.39.10"
args:
dependency: transitive
description:
@ -56,7 +49,7 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.2"
version: "1.3.0"
build_config:
dependency: transitive
description:
@ -77,21 +70,21 @@ packages:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.7"
version: "1.3.9"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
version: "1.10.0"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
version: "5.2.0"
built_collection:
dependency: "direct main"
description:
@ -134,13 +127,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.1"
version: "3.3.0"
collection:
dependency: transitive
description:
@ -161,14 +161,14 @@ packages:
name: coverage
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.9"
version: "0.13.10"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
version: "2.1.5"
csslib:
dependency: transitive
description:
@ -190,12 +190,19 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.6"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
file_chooser:
dependency: "direct main"
description:
path: "plugins/file_chooser"
ref: HEAD
resolved-ref: "100bc306dd15532dbbb2b353170aea47e8173a13"
resolved-ref: b9c7e27ba16f86ff3390cfb0e460802e9980399a
url: "https://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.1.0"
@ -211,6 +218,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_simple_treeview:
dependency: "direct main"
description:
name: flutter_simple_treeview
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -270,13 +284,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.12"
intl:
dependency: transitive
description:
@ -324,7 +331,7 @@ packages:
description:
path: "plugins/menubar"
ref: HEAD
resolved-ref: "100bc306dd15532dbbb2b353170aea47e8173a13"
resolved-ref: b9c7e27ba16f86ff3390cfb0e460802e9980399a
url: "https://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.0.1"
@ -362,21 +369,21 @@ packages:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "1.1.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
node_preamble:
dependency: transitive
description:
name: node_preamble
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.8"
version: "1.4.10"
package_config:
dependency: transitive
description:
@ -390,7 +397,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
version: "1.7.0"
pedantic:
dependency: "direct main"
description:
@ -398,13 +405,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
petitparser:
platform_detect:
dependency: transitive
description:
name: petitparser
name: platform_detect
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
version: "1.4.0"
plugin_platform_interface:
dependency: transitive
description:
@ -425,7 +432,7 @@ packages:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "4.1.2"
pub_semver:
dependency: transitive
description:
@ -549,21 +556,21 @@ packages:
name: test
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.3"
version: "1.14.6"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.15"
version: "0.2.16"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.4"
version: "0.3.6"
timing:
dependency: transitive
description:
@ -598,28 +605,28 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.5"
version: "5.4.10"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+5"
version: "0.0.1+7"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.6"
version: "1.0.7"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1+4"
version: "0.1.1+6"
uuid:
dependency: "direct main"
description:
@ -640,7 +647,7 @@ packages:
name: vm_service
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.2"
version: "4.0.4"
watcher:
dependency: transitive
description:
@ -661,14 +668,7 @@ packages:
name: webkit_inspection_protocol
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.3"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.1"
version: "0.7.3"
yaml:
dependency: transitive
description:
@ -677,5 +677,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.7.0 <3.0.0"
flutter: ">=1.17.0 <2.0.0"
dart: ">=2.9.0-11.0.dev <3.0.0"
flutter: ">=1.19.0-3.0.pre <2.0.0"

@ -3,8 +3,8 @@ description: Search for Photos, using the Unsplash API.
version: 1.0.0+1
environment:
sdk: ^2.7.0-dev
flutter: ^1.13.1-pre
sdk: ^2.9.0-11.0.dev
flutter: ^1.19.0-3.0.pre
dependencies:
flutter:
@ -17,6 +17,7 @@ dependencies:
url: https://github.com/google/flutter-desktop-embedding.git
path: plugins/file_chooser
logging: ^0.11.3+2
flutter_simple_treeview: ^2.0.1
menubar:
git:
url: https://github.com/google/flutter-desktop-embedding.git

Loading…
Cancel
Save