Migrate desktop_photo_search to top level (#1002)
37
experimental/desktop_photo_search/.gitignore
vendored
@@ -1,37 +0,0 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Exceptions to above rules.
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
@@ -1,10 +0,0 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 7caef218b55acac803aa67e7393e97f75ec70c5c
|
||||
channel: master
|
||||
|
||||
project_type: app
|
||||
@@ -1,74 +1,3 @@
|
||||
# Photo Search app
|
||||
|
||||
This desktop application enables you to search
|
||||
[Unsplash](https://unsplash.com/) for photographs that interest you.
|
||||
To use it, you need to add an **Access Key** from
|
||||
[Unsplash API](https://unsplash.com/developers) to
|
||||
`lib/unsplash_access_key.dart`.
|
||||
|
||||
This sample works on Windows, macOS and Linux.
|
||||
|
||||
## A quick tour of the code
|
||||
|
||||
This Flutter project builds a desktop application. It utilises the following
|
||||
desktop specific plugins:
|
||||
|
||||
- [file_chooser] to enable the application user to select where to save a photo
|
||||
from the Unsplash API.
|
||||
- [menubar] for exposing Image Search functionality through the menu bar.
|
||||
- [url_launcher] to open external links.
|
||||
|
||||
The Unsplash API client entry point is in the [Unsplash] class, and is built
|
||||
atop [http], [built_value] and [built_collection] for JSON Rest API access.
|
||||
|
||||
The [DataTreeNode] and widget family, along with the [Split] widget capture
|
||||
desktop file explorer master/detail view idioms.
|
||||
|
||||
## Deploying to the Microsoft Store
|
||||
|
||||
This sample uses Yehuda Kremer's [MSIX pub package][msix_pub_package]
|
||||
to bundle up the Windows release build for distribution to the
|
||||
[Microsoft Store][]. Microsoft maintains a [plethora of documentation][ms_store_publishing_doc]
|
||||
on deploying to the Microsoft Store.
|
||||
|
||||
See the `msix_config` stanza in this sample's `pubspec.yaml` for an
|
||||
example configuration. Make sure the `display_name`, `publisher_display_name`,
|
||||
`publisher` and `identity_name` attributes match the settings in your
|
||||
Microsoft Partner Center application submission.
|
||||
|
||||
## macOS Network and File entitlements
|
||||
|
||||
To access the network, macOS requires applications enable the
|
||||
[com.apple.security.network.client entitlement][macOS-client]. For this
|
||||
sample, this entitlement is required to access the Unsplash API.
|
||||
|
||||
Likewise, to save a Photo to the local file system using the `file_chooser` plugin requires the
|
||||
[com.apple.security.files.user-selected.read-write entitlement][macOS-read-write].
|
||||
|
||||
Please see [macOS Signing and Security][macOS-security] for more detail.
|
||||
|
||||
## Flutter Desktop is in Beta
|
||||
|
||||
Flutter's Desktop support is now in `beta`, with a snapshot available in the
|
||||
`stable` channel. Please see the [setup documentation][] for how to configure
|
||||
your development environment to enable Flutter's Desktop support.
|
||||
|
||||
[DataTreeNode]: lib/src/widgets/data_tree.dart
|
||||
[Split]: lib/src/widgets/split.dart
|
||||
[Unsplash]: lib/src/unsplash/unsplash.dart
|
||||
|
||||
[built_collection]: https://pub.dev/packages/built_collection
|
||||
[built_value]: https://pub.dev/packages/built_value
|
||||
[file_chooser]: https://github.com/google/flutter-desktop-embedding/tree/master/plugins/file_chooser
|
||||
[flutter_channels]: https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
|
||||
[http]: https://pub.dev/packages/http
|
||||
[macOS-client]: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_network_client
|
||||
[macOS-read-write]: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_files_user-selected_read-write
|
||||
[macOS-security]: https://github.com/google/flutter-desktop-embedding/blob/master/macOS-Security.md
|
||||
[menubar]: https://github.com/google/flutter-desktop-embedding/tree/master/plugins/menubar
|
||||
[setup documentation]: https://flutter.dev/desktop#set-up
|
||||
[url_launcher]: https://pub.dev/packages/url_launcher
|
||||
|
||||
[msix_pub_package]: https://pub.dev/packages/msix
|
||||
[Microsoft Store]: https://www.microsoft.com/en-au/p/flutter-desktop-photo-search/9nh719dxcpj4
|
||||
[ms_store_publishing_doc]: https://docs.microsoft.com/en-us/windows/uwp/publish/
|
||||
This application has been moved to the [top level of this repo](../../desktop_photo_search).
|
||||
@@ -1 +0,0 @@
|
||||
include: ../../analysis_options.yaml
|
||||
@@ -1,188 +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 'dart:io';
|
||||
|
||||
import 'package:file_selector/file_selector.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_simple_treeview/flutter_simple_treeview.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:menubar/menubar.dart' as menubar;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'src/model/photo_search_model.dart';
|
||||
import 'src/unsplash/photo.dart';
|
||||
import 'src/unsplash/unsplash.dart';
|
||||
import 'src/widgets/about_dialog.dart';
|
||||
import 'src/widgets/photo_details.dart';
|
||||
import 'src/widgets/photo_search_dialog.dart';
|
||||
import 'src/widgets/split.dart';
|
||||
import 'unsplash_access_key.dart';
|
||||
|
||||
void main() {
|
||||
Logger.root.level = Level.ALL;
|
||||
Logger.root.onRecord.listen((rec) {
|
||||
// ignore: avoid_print
|
||||
print('${rec.loggerName} ${rec.level.name}: ${rec.time}: ${rec.message}');
|
||||
});
|
||||
|
||||
if (unsplashAccessKey.isEmpty) {
|
||||
Logger('main').severe('Unsplash Access Key is required. '
|
||||
'Please add to `lib/unsplash_access_key.dart`.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
runApp(
|
||||
ChangeNotifierProvider<PhotoSearchModel>(
|
||||
create: (context) => PhotoSearchModel(
|
||||
Unsplash(accessKey: unsplashAccessKey),
|
||||
),
|
||||
child: const UnsplashSearchApp(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class UnsplashSearchApp extends StatelessWidget {
|
||||
const UnsplashSearchApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Photo Search',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.orange,
|
||||
),
|
||||
home: const UnsplashHomePage(title: 'Photo Search'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UnsplashHomePage extends StatelessWidget {
|
||||
const UnsplashHomePage({required this.title, Key? key}) : super(key: key);
|
||||
final String title;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final photoSearchModel = Provider.of<PhotoSearchModel>(context);
|
||||
menubar.setApplicationMenu([
|
||||
menubar.Submenu(label: 'Search', children: [
|
||||
menubar.MenuItem(
|
||||
label: 'Search ...',
|
||||
onClicked: () {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
PhotoSearchDialog(callback: photoSearchModel.addSearch),
|
||||
);
|
||||
},
|
||||
),
|
||||
]),
|
||||
menubar.Submenu(label: 'About', children: [
|
||||
menubar.MenuItem(
|
||||
label: 'About ...',
|
||||
onClicked: () {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => const PolicyDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
])
|
||||
]);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(title),
|
||||
),
|
||||
body: photoSearchModel.entries.isNotEmpty
|
||||
? Split(
|
||||
axis: Axis.horizontal,
|
||||
initialFirstFraction: 0.4,
|
||||
firstChild: Scrollbar(
|
||||
child: SingleChildScrollView(
|
||||
child: TreeView(
|
||||
nodes: photoSearchModel.entries
|
||||
.map(_buildSearchEntry)
|
||||
.toList(),
|
||||
indent: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
secondChild: Center(
|
||||
child: photoSearchModel.selectedPhoto != null
|
||||
? PhotoDetails(
|
||||
photo: photoSearchModel.selectedPhoto!,
|
||||
onPhotoSave: (photo) async {
|
||||
final path = await getSavePath(
|
||||
suggestedName: '${photo.id}.jpg',
|
||||
acceptedTypeGroups: [
|
||||
XTypeGroup(
|
||||
label: 'JPG',
|
||||
extensions: ['jpg'],
|
||||
mimeTypes: ['image/jpeg'],
|
||||
),
|
||||
],
|
||||
);
|
||||
if (path != null) {
|
||||
final fileData =
|
||||
await photoSearchModel.download(photo: photo);
|
||||
final photoFile = XFile.fromData(fileData,
|
||||
mimeType: 'image/jpeg');
|
||||
await photoFile.saveTo(path);
|
||||
}
|
||||
},
|
||||
)
|
||||
: Container(),
|
||||
),
|
||||
)
|
||||
: const Center(
|
||||
child: Text('Search for Photos using the Fab button'),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
PhotoSearchDialog(callback: photoSearchModel.addSearch),
|
||||
),
|
||||
tooltip: 'Search for a photo',
|
||||
child: const Icon(Icons.search),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TreeNode _buildSearchEntry(SearchEntry searchEntry) {
|
||||
void selectPhoto(Photo photo) {
|
||||
searchEntry.model.selectedPhoto = photo;
|
||||
}
|
||||
|
||||
String labelForPhoto(Photo photo) => 'Photo by ${photo.user!.name}';
|
||||
|
||||
return TreeNode(
|
||||
content: Expanded(
|
||||
child: Text(searchEntry.query),
|
||||
),
|
||||
children: searchEntry.photos
|
||||
.map<TreeNode>(
|
||||
(photo) => TreeNode(
|
||||
content: Expanded(
|
||||
child: Semantics(
|
||||
button: true,
|
||||
onTap: () => selectPhoto(photo),
|
||||
label: labelForPhoto(photo),
|
||||
excludeSemantics: true,
|
||||
child: InkWell(
|
||||
onTap: () => selectPhoto(photo),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Text(labelForPhoto(photo)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +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 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../unsplash/photo.dart';
|
||||
import '../unsplash/unsplash.dart';
|
||||
import 'search.dart';
|
||||
|
||||
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<SearchEntry> get entries => List.unmodifiable(_entries);
|
||||
final List<SearchEntry> _entries = [];
|
||||
|
||||
Photo? get selectedPhoto => _selectedPhoto;
|
||||
set selectedPhoto(Photo? photo) {
|
||||
_selectedPhoto = photo;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Photo? _selectedPhoto;
|
||||
|
||||
Future<void> addSearch(String query) async {
|
||||
final result = await _client.searchPhotos(
|
||||
query: query,
|
||||
orientation: SearchPhotosOrientation.portrait,
|
||||
);
|
||||
final search = Search((s) {
|
||||
s
|
||||
..query = query
|
||||
..results.addAll(result!.results);
|
||||
});
|
||||
|
||||
_entries.add(SearchEntry(query, search.results.toList(), this));
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<Uint8List> download({required Photo photo}) => _client.download(photo);
|
||||
}
|
||||
@@ -1,36 +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 'dart:convert';
|
||||
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
import '../unsplash/photo.dart';
|
||||
|
||||
part 'search.g.dart';
|
||||
|
||||
abstract class Search implements Built<Search, SearchBuilder> {
|
||||
factory Search([void Function(SearchBuilder)? updates]) = _$Search;
|
||||
Search._();
|
||||
|
||||
@BuiltValueField(wireName: 'query')
|
||||
String get query;
|
||||
|
||||
@BuiltValueField(wireName: 'results')
|
||||
BuiltList<Photo> get results;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Search.serializer, this));
|
||||
}
|
||||
|
||||
static Search? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Search.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Search> get serializer => _$searchSerializer;
|
||||
}
|
||||
@@ -1,166 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'search.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Search> _$searchSerializer = new _$SearchSerializer();
|
||||
|
||||
class _$SearchSerializer implements StructuredSerializer<Search> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Search, _$Search];
|
||||
@override
|
||||
final String wireName = 'Search';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Search object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'query',
|
||||
serializers.serialize(object.query,
|
||||
specifiedType: const FullType(String)),
|
||||
'results',
|
||||
serializers.serialize(object.results,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Photo)])),
|
||||
];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Search deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new SearchBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'query':
|
||||
result.query = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'results':
|
||||
result.results.replace(serializers.deserialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Photo)]))!
|
||||
as BuiltList<Object>);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Search extends Search {
|
||||
@override
|
||||
final String query;
|
||||
@override
|
||||
final BuiltList<Photo> results;
|
||||
|
||||
factory _$Search([void Function(SearchBuilder)? updates]) =>
|
||||
(new SearchBuilder()..update(updates)).build();
|
||||
|
||||
_$Search._({required this.query, required this.results}) : super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(query, 'Search', 'query');
|
||||
BuiltValueNullFieldError.checkNotNull(results, 'Search', 'results');
|
||||
}
|
||||
|
||||
@override
|
||||
Search rebuild(void Function(SearchBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
SearchBuilder toBuilder() => new SearchBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Search && query == other.query && results == other.results;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc($jc(0, query.hashCode), results.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Search')
|
||||
..add('query', query)
|
||||
..add('results', results))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class SearchBuilder implements Builder<Search, SearchBuilder> {
|
||||
_$Search? _$v;
|
||||
|
||||
String? _query;
|
||||
String? get query => _$this._query;
|
||||
set query(String? query) => _$this._query = query;
|
||||
|
||||
ListBuilder<Photo>? _results;
|
||||
ListBuilder<Photo> get results =>
|
||||
_$this._results ??= new ListBuilder<Photo>();
|
||||
set results(ListBuilder<Photo>? results) => _$this._results = results;
|
||||
|
||||
SearchBuilder();
|
||||
|
||||
SearchBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_query = $v.query;
|
||||
_results = $v.results.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Search other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Search;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(SearchBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Search build() {
|
||||
_$Search _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$Search._(
|
||||
query: BuiltValueNullFieldError.checkNotNull(
|
||||
query, 'Search', 'query'),
|
||||
results: results.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'results';
|
||||
results.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'Search', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,27 +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:built_collection/built_collection.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
import 'package:built_value/standard_json_plugin.dart';
|
||||
|
||||
import 'model/search.dart';
|
||||
import 'unsplash/api_error.dart';
|
||||
import 'unsplash/current_user_collections.dart';
|
||||
import 'unsplash/exif.dart';
|
||||
import 'unsplash/links.dart';
|
||||
import 'unsplash/location.dart';
|
||||
import 'unsplash/photo.dart';
|
||||
import 'unsplash/position.dart';
|
||||
import 'unsplash/search_photos_response.dart';
|
||||
import 'unsplash/tags.dart';
|
||||
import 'unsplash/urls.dart';
|
||||
import 'unsplash/user.dart';
|
||||
|
||||
part 'serializers.g.dart';
|
||||
|
||||
//add all of the built value types that require serialization
|
||||
@SerializersFor([Search, ApiError, Photo, SearchPhotosResponse])
|
||||
final Serializers serializers =
|
||||
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
|
||||
@@ -1,44 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'serializers.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializers _$serializers = (new Serializers().toBuilder()
|
||||
..add(ApiError.serializer)
|
||||
..add(CurrentUserCollections.serializer)
|
||||
..add(Exif.serializer)
|
||||
..add(Links.serializer)
|
||||
..add(Location.serializer)
|
||||
..add(Photo.serializer)
|
||||
..add(Position.serializer)
|
||||
..add(Search.serializer)
|
||||
..add(SearchPhotosResponse.serializer)
|
||||
..add(Tags.serializer)
|
||||
..add(Urls.serializer)
|
||||
..add(User.serializer)
|
||||
..addBuilderFactory(
|
||||
const FullType(BuiltList, const [const FullType(Photo)]),
|
||||
() => new ListBuilder<Photo>())
|
||||
..addBuilderFactory(
|
||||
const FullType(BuiltList, const [const FullType(Photo)]),
|
||||
() => new ListBuilder<Photo>())
|
||||
..addBuilderFactory(
|
||||
const FullType(BuiltList, const [const FullType(String)]),
|
||||
() => new ListBuilder<String>())
|
||||
..addBuilderFactory(
|
||||
const FullType(BuiltList, const [const FullType(Tags)]),
|
||||
() => new ListBuilder<Tags>())
|
||||
..addBuilderFactory(
|
||||
const FullType(
|
||||
BuiltList, const [const FullType(CurrentUserCollections)]),
|
||||
() => new ListBuilder<CurrentUserCollections>()))
|
||||
.build();
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,33 +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 'dart:convert';
|
||||
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'api_error.g.dart';
|
||||
|
||||
abstract class ApiError implements Built<ApiError, ApiErrorBuilder> {
|
||||
factory ApiError([void Function(ApiErrorBuilder)? updates]) = _$ApiError;
|
||||
|
||||
ApiError._();
|
||||
|
||||
@BuiltValueField(wireName: 'errors')
|
||||
BuiltList<String>? get errors;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(ApiError.serializer, this));
|
||||
}
|
||||
|
||||
static ApiError? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
ApiError.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<ApiError> get serializer => _$apiErrorSerializer;
|
||||
}
|
||||
@@ -1,146 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'api_error.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<ApiError> _$apiErrorSerializer = new _$ApiErrorSerializer();
|
||||
|
||||
class _$ApiErrorSerializer implements StructuredSerializer<ApiError> {
|
||||
@override
|
||||
final Iterable<Type> types = const [ApiError, _$ApiError];
|
||||
@override
|
||||
final String wireName = 'ApiError';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, ApiError object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[];
|
||||
Object? value;
|
||||
value = object.errors;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('errors')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(String)])));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
ApiError deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new ApiErrorBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'errors':
|
||||
result.errors.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(
|
||||
BuiltList, const [const FullType(String)]))!
|
||||
as BuiltList<Object>);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$ApiError extends ApiError {
|
||||
@override
|
||||
final BuiltList<String>? errors;
|
||||
|
||||
factory _$ApiError([void Function(ApiErrorBuilder)? updates]) =>
|
||||
(new ApiErrorBuilder()..update(updates)).build();
|
||||
|
||||
_$ApiError._({this.errors}) : super._();
|
||||
|
||||
@override
|
||||
ApiError rebuild(void Function(ApiErrorBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
ApiErrorBuilder toBuilder() => new ApiErrorBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is ApiError && errors == other.errors;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(0, errors.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('ApiError')..add('errors', errors))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class ApiErrorBuilder implements Builder<ApiError, ApiErrorBuilder> {
|
||||
_$ApiError? _$v;
|
||||
|
||||
ListBuilder<String>? _errors;
|
||||
ListBuilder<String> get errors =>
|
||||
_$this._errors ??= new ListBuilder<String>();
|
||||
set errors(ListBuilder<String>? errors) => _$this._errors = errors;
|
||||
|
||||
ApiErrorBuilder();
|
||||
|
||||
ApiErrorBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_errors = $v.errors?.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(ApiError other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$ApiError;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(ApiErrorBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$ApiError build() {
|
||||
_$ApiError _$result;
|
||||
try {
|
||||
_$result = _$v ?? new _$ApiError._(errors: _errors?.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'errors';
|
||||
_errors?.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'ApiError', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,46 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'current_user_collections.g.dart';
|
||||
|
||||
abstract class CurrentUserCollections
|
||||
implements Built<CurrentUserCollections, CurrentUserCollectionsBuilder> {
|
||||
factory CurrentUserCollections(
|
||||
[void Function(CurrentUserCollectionsBuilder)? updates]) =
|
||||
_$CurrentUserCollections;
|
||||
|
||||
CurrentUserCollections._();
|
||||
|
||||
@BuiltValueField(wireName: 'id')
|
||||
int get id;
|
||||
|
||||
@BuiltValueField(wireName: 'title')
|
||||
String? get title;
|
||||
|
||||
@BuiltValueField(wireName: 'published_at')
|
||||
String? get publishedAt;
|
||||
|
||||
@BuiltValueField(wireName: 'updated_at')
|
||||
String? get updatedAt;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(
|
||||
serializers.serializeWith(CurrentUserCollections.serializer, this));
|
||||
}
|
||||
|
||||
static CurrentUserCollections? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
CurrentUserCollections.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<CurrentUserCollections> get serializer =>
|
||||
_$currentUserCollectionsSerializer;
|
||||
}
|
||||
@@ -1,210 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'current_user_collections.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<CurrentUserCollections> _$currentUserCollectionsSerializer =
|
||||
new _$CurrentUserCollectionsSerializer();
|
||||
|
||||
class _$CurrentUserCollectionsSerializer
|
||||
implements StructuredSerializer<CurrentUserCollections> {
|
||||
@override
|
||||
final Iterable<Type> types = const [
|
||||
CurrentUserCollections,
|
||||
_$CurrentUserCollections
|
||||
];
|
||||
@override
|
||||
final String wireName = 'CurrentUserCollections';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(
|
||||
Serializers serializers, CurrentUserCollections object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'id',
|
||||
serializers.serialize(object.id, specifiedType: const FullType(int)),
|
||||
];
|
||||
Object? value;
|
||||
value = object.title;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('title')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.publishedAt;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('published_at')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.updatedAt;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('updated_at')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
CurrentUserCollections deserialize(
|
||||
Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new CurrentUserCollectionsBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'id':
|
||||
result.id = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'title':
|
||||
result.title = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'published_at':
|
||||
result.publishedAt = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'updated_at':
|
||||
result.updatedAt = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$CurrentUserCollections extends CurrentUserCollections {
|
||||
@override
|
||||
final int id;
|
||||
@override
|
||||
final String? title;
|
||||
@override
|
||||
final String? publishedAt;
|
||||
@override
|
||||
final String? updatedAt;
|
||||
|
||||
factory _$CurrentUserCollections(
|
||||
[void Function(CurrentUserCollectionsBuilder)? updates]) =>
|
||||
(new CurrentUserCollectionsBuilder()..update(updates)).build();
|
||||
|
||||
_$CurrentUserCollections._(
|
||||
{required this.id, this.title, this.publishedAt, this.updatedAt})
|
||||
: super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(id, 'CurrentUserCollections', 'id');
|
||||
}
|
||||
|
||||
@override
|
||||
CurrentUserCollections rebuild(
|
||||
void Function(CurrentUserCollectionsBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
CurrentUserCollectionsBuilder toBuilder() =>
|
||||
new CurrentUserCollectionsBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is CurrentUserCollections &&
|
||||
id == other.id &&
|
||||
title == other.title &&
|
||||
publishedAt == other.publishedAt &&
|
||||
updatedAt == other.updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc($jc($jc(0, id.hashCode), title.hashCode), publishedAt.hashCode),
|
||||
updatedAt.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('CurrentUserCollections')
|
||||
..add('id', id)
|
||||
..add('title', title)
|
||||
..add('publishedAt', publishedAt)
|
||||
..add('updatedAt', updatedAt))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class CurrentUserCollectionsBuilder
|
||||
implements Builder<CurrentUserCollections, CurrentUserCollectionsBuilder> {
|
||||
_$CurrentUserCollections? _$v;
|
||||
|
||||
int? _id;
|
||||
int? get id => _$this._id;
|
||||
set id(int? id) => _$this._id = id;
|
||||
|
||||
String? _title;
|
||||
String? get title => _$this._title;
|
||||
set title(String? title) => _$this._title = title;
|
||||
|
||||
String? _publishedAt;
|
||||
String? get publishedAt => _$this._publishedAt;
|
||||
set publishedAt(String? publishedAt) => _$this._publishedAt = publishedAt;
|
||||
|
||||
String? _updatedAt;
|
||||
String? get updatedAt => _$this._updatedAt;
|
||||
set updatedAt(String? updatedAt) => _$this._updatedAt = updatedAt;
|
||||
|
||||
CurrentUserCollectionsBuilder();
|
||||
|
||||
CurrentUserCollectionsBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_id = $v.id;
|
||||
_title = $v.title;
|
||||
_publishedAt = $v.publishedAt;
|
||||
_updatedAt = $v.updatedAt;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(CurrentUserCollections other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$CurrentUserCollections;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(CurrentUserCollectionsBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$CurrentUserCollections build() {
|
||||
final _$result = _$v ??
|
||||
new _$CurrentUserCollections._(
|
||||
id: BuiltValueNullFieldError.checkNotNull(
|
||||
id, 'CurrentUserCollections', 'id'),
|
||||
title: title,
|
||||
publishedAt: publishedAt,
|
||||
updatedAt: updatedAt);
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,47 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'exif.g.dart';
|
||||
|
||||
abstract class Exif implements Built<Exif, ExifBuilder> {
|
||||
factory Exif([void Function(ExifBuilder)? updates]) = _$Exif;
|
||||
|
||||
Exif._();
|
||||
|
||||
@BuiltValueField(wireName: 'make')
|
||||
String? get make;
|
||||
|
||||
@BuiltValueField(wireName: 'model')
|
||||
String? get model;
|
||||
|
||||
@BuiltValueField(wireName: 'exposure_time')
|
||||
String? get exposureTime;
|
||||
|
||||
@BuiltValueField(wireName: 'aperture')
|
||||
String? get aperture;
|
||||
|
||||
@BuiltValueField(wireName: 'focal_length')
|
||||
String? get focalLength;
|
||||
|
||||
@BuiltValueField(wireName: 'iso')
|
||||
int? get iso;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Exif.serializer, this));
|
||||
}
|
||||
|
||||
static Exif? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Exif.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Exif> get serializer => _$exifSerializer;
|
||||
}
|
||||
@@ -1,251 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'exif.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Exif> _$exifSerializer = new _$ExifSerializer();
|
||||
|
||||
class _$ExifSerializer implements StructuredSerializer<Exif> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Exif, _$Exif];
|
||||
@override
|
||||
final String wireName = 'Exif';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Exif object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[];
|
||||
Object? value;
|
||||
value = object.make;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('make')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.model;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('model')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.exposureTime;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('exposure_time')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.aperture;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('aperture')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.focalLength;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('focal_length')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.iso;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('iso')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Exif deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new ExifBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'make':
|
||||
result.make = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'model':
|
||||
result.model = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'exposure_time':
|
||||
result.exposureTime = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'aperture':
|
||||
result.aperture = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'focal_length':
|
||||
result.focalLength = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'iso':
|
||||
result.iso = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Exif extends Exif {
|
||||
@override
|
||||
final String? make;
|
||||
@override
|
||||
final String? model;
|
||||
@override
|
||||
final String? exposureTime;
|
||||
@override
|
||||
final String? aperture;
|
||||
@override
|
||||
final String? focalLength;
|
||||
@override
|
||||
final int? iso;
|
||||
|
||||
factory _$Exif([void Function(ExifBuilder)? updates]) =>
|
||||
(new ExifBuilder()..update(updates)).build();
|
||||
|
||||
_$Exif._(
|
||||
{this.make,
|
||||
this.model,
|
||||
this.exposureTime,
|
||||
this.aperture,
|
||||
this.focalLength,
|
||||
this.iso})
|
||||
: super._();
|
||||
|
||||
@override
|
||||
Exif rebuild(void Function(ExifBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
ExifBuilder toBuilder() => new ExifBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Exif &&
|
||||
make == other.make &&
|
||||
model == other.model &&
|
||||
exposureTime == other.exposureTime &&
|
||||
aperture == other.aperture &&
|
||||
focalLength == other.focalLength &&
|
||||
iso == other.iso;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc($jc($jc(0, make.hashCode), model.hashCode),
|
||||
exposureTime.hashCode),
|
||||
aperture.hashCode),
|
||||
focalLength.hashCode),
|
||||
iso.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Exif')
|
||||
..add('make', make)
|
||||
..add('model', model)
|
||||
..add('exposureTime', exposureTime)
|
||||
..add('aperture', aperture)
|
||||
..add('focalLength', focalLength)
|
||||
..add('iso', iso))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class ExifBuilder implements Builder<Exif, ExifBuilder> {
|
||||
_$Exif? _$v;
|
||||
|
||||
String? _make;
|
||||
String? get make => _$this._make;
|
||||
set make(String? make) => _$this._make = make;
|
||||
|
||||
String? _model;
|
||||
String? get model => _$this._model;
|
||||
set model(String? model) => _$this._model = model;
|
||||
|
||||
String? _exposureTime;
|
||||
String? get exposureTime => _$this._exposureTime;
|
||||
set exposureTime(String? exposureTime) => _$this._exposureTime = exposureTime;
|
||||
|
||||
String? _aperture;
|
||||
String? get aperture => _$this._aperture;
|
||||
set aperture(String? aperture) => _$this._aperture = aperture;
|
||||
|
||||
String? _focalLength;
|
||||
String? get focalLength => _$this._focalLength;
|
||||
set focalLength(String? focalLength) => _$this._focalLength = focalLength;
|
||||
|
||||
int? _iso;
|
||||
int? get iso => _$this._iso;
|
||||
set iso(int? iso) => _$this._iso = iso;
|
||||
|
||||
ExifBuilder();
|
||||
|
||||
ExifBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_make = $v.make;
|
||||
_model = $v.model;
|
||||
_exposureTime = $v.exposureTime;
|
||||
_aperture = $v.aperture;
|
||||
_focalLength = $v.focalLength;
|
||||
_iso = $v.iso;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Exif other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Exif;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(ExifBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Exif build() {
|
||||
final _$result = _$v ??
|
||||
new _$Exif._(
|
||||
make: make,
|
||||
model: model,
|
||||
exposureTime: exposureTime,
|
||||
aperture: aperture,
|
||||
focalLength: focalLength,
|
||||
iso: iso);
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,41 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'links.g.dart';
|
||||
|
||||
abstract class Links implements Built<Links, LinksBuilder> {
|
||||
factory Links([void Function(LinksBuilder)? updates]) = _$Links;
|
||||
|
||||
Links._();
|
||||
|
||||
@BuiltValueField(wireName: 'self')
|
||||
String? get self;
|
||||
|
||||
@BuiltValueField(wireName: 'html')
|
||||
String? get html;
|
||||
|
||||
@BuiltValueField(wireName: 'download')
|
||||
String? get download;
|
||||
|
||||
@BuiltValueField(wireName: 'download_location')
|
||||
String? get downloadLocation;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Links.serializer, this));
|
||||
}
|
||||
|
||||
static Links? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Links.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Links> get serializer => _$linksSerializer;
|
||||
}
|
||||
@@ -1,200 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'links.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Links> _$linksSerializer = new _$LinksSerializer();
|
||||
|
||||
class _$LinksSerializer implements StructuredSerializer<Links> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Links, _$Links];
|
||||
@override
|
||||
final String wireName = 'Links';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Links object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[];
|
||||
Object? value;
|
||||
value = object.self;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('self')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.html;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('html')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.download;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('download')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.downloadLocation;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('download_location')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Links deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new LinksBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'self':
|
||||
result.self = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'html':
|
||||
result.html = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'download':
|
||||
result.download = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'download_location':
|
||||
result.downloadLocation = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Links extends Links {
|
||||
@override
|
||||
final String? self;
|
||||
@override
|
||||
final String? html;
|
||||
@override
|
||||
final String? download;
|
||||
@override
|
||||
final String? downloadLocation;
|
||||
|
||||
factory _$Links([void Function(LinksBuilder)? updates]) =>
|
||||
(new LinksBuilder()..update(updates)).build();
|
||||
|
||||
_$Links._({this.self, this.html, this.download, this.downloadLocation})
|
||||
: super._();
|
||||
|
||||
@override
|
||||
Links rebuild(void Function(LinksBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
LinksBuilder toBuilder() => new LinksBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Links &&
|
||||
self == other.self &&
|
||||
html == other.html &&
|
||||
download == other.download &&
|
||||
downloadLocation == other.downloadLocation;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc($jc($jc(0, self.hashCode), html.hashCode), download.hashCode),
|
||||
downloadLocation.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Links')
|
||||
..add('self', self)
|
||||
..add('html', html)
|
||||
..add('download', download)
|
||||
..add('downloadLocation', downloadLocation))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class LinksBuilder implements Builder<Links, LinksBuilder> {
|
||||
_$Links? _$v;
|
||||
|
||||
String? _self;
|
||||
String? get self => _$this._self;
|
||||
set self(String? self) => _$this._self = self;
|
||||
|
||||
String? _html;
|
||||
String? get html => _$this._html;
|
||||
set html(String? html) => _$this._html = html;
|
||||
|
||||
String? _download;
|
||||
String? get download => _$this._download;
|
||||
set download(String? download) => _$this._download = download;
|
||||
|
||||
String? _downloadLocation;
|
||||
String? get downloadLocation => _$this._downloadLocation;
|
||||
set downloadLocation(String? downloadLocation) =>
|
||||
_$this._downloadLocation = downloadLocation;
|
||||
|
||||
LinksBuilder();
|
||||
|
||||
LinksBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_self = $v.self;
|
||||
_html = $v.html;
|
||||
_download = $v.download;
|
||||
_downloadLocation = $v.downloadLocation;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Links other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Links;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(LinksBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Links build() {
|
||||
final _$result = _$v ??
|
||||
new _$Links._(
|
||||
self: self,
|
||||
html: html,
|
||||
download: download,
|
||||
downloadLocation: downloadLocation);
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,39 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
import 'position.dart';
|
||||
|
||||
part 'location.g.dart';
|
||||
|
||||
abstract class Location implements Built<Location, LocationBuilder> {
|
||||
factory Location([void Function(LocationBuilder)? updates]) = _$Location;
|
||||
|
||||
Location._();
|
||||
|
||||
@BuiltValueField(wireName: 'city')
|
||||
String? get city;
|
||||
|
||||
@BuiltValueField(wireName: 'country')
|
||||
String? get country;
|
||||
|
||||
@BuiltValueField(wireName: 'position')
|
||||
Position? get position;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Location.serializer, this));
|
||||
}
|
||||
|
||||
static Location? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Location.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Location> get serializer => _$locationSerializer;
|
||||
}
|
||||
@@ -1,187 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'location.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Location> _$locationSerializer = new _$LocationSerializer();
|
||||
|
||||
class _$LocationSerializer implements StructuredSerializer<Location> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Location, _$Location];
|
||||
@override
|
||||
final String wireName = 'Location';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Location object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[];
|
||||
Object? value;
|
||||
value = object.city;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('city')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.country;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('country')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.position;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('position')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(Position)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Location deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new LocationBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'city':
|
||||
result.city = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'country':
|
||||
result.country = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'position':
|
||||
result.position.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Position))! as Position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Location extends Location {
|
||||
@override
|
||||
final String? city;
|
||||
@override
|
||||
final String? country;
|
||||
@override
|
||||
final Position? position;
|
||||
|
||||
factory _$Location([void Function(LocationBuilder)? updates]) =>
|
||||
(new LocationBuilder()..update(updates)).build();
|
||||
|
||||
_$Location._({this.city, this.country, this.position}) : super._();
|
||||
|
||||
@override
|
||||
Location rebuild(void Function(LocationBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
LocationBuilder toBuilder() => new LocationBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Location &&
|
||||
city == other.city &&
|
||||
country == other.country &&
|
||||
position == other.position;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf(
|
||||
$jc($jc($jc(0, city.hashCode), country.hashCode), position.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Location')
|
||||
..add('city', city)
|
||||
..add('country', country)
|
||||
..add('position', position))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class LocationBuilder implements Builder<Location, LocationBuilder> {
|
||||
_$Location? _$v;
|
||||
|
||||
String? _city;
|
||||
String? get city => _$this._city;
|
||||
set city(String? city) => _$this._city = city;
|
||||
|
||||
String? _country;
|
||||
String? get country => _$this._country;
|
||||
set country(String? country) => _$this._country = country;
|
||||
|
||||
PositionBuilder? _position;
|
||||
PositionBuilder get position => _$this._position ??= new PositionBuilder();
|
||||
set position(PositionBuilder? position) => _$this._position = position;
|
||||
|
||||
LocationBuilder();
|
||||
|
||||
LocationBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_city = $v.city;
|
||||
_country = $v.country;
|
||||
_position = $v.position?.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Location other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Location;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(LocationBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Location build() {
|
||||
_$Location _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$Location._(
|
||||
city: city, country: country, position: _position?.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'position';
|
||||
_position?.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'Location', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,88 +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 'dart:convert';
|
||||
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
import 'current_user_collections.dart';
|
||||
import 'exif.dart';
|
||||
import 'links.dart';
|
||||
import 'location.dart';
|
||||
import 'tags.dart';
|
||||
import 'urls.dart';
|
||||
import 'user.dart';
|
||||
|
||||
part 'photo.g.dart';
|
||||
|
||||
abstract class Photo implements Built<Photo, PhotoBuilder> {
|
||||
factory Photo([void Function(PhotoBuilder)? updates]) = _$Photo;
|
||||
|
||||
Photo._();
|
||||
|
||||
@BuiltValueField(wireName: 'id')
|
||||
String get id;
|
||||
|
||||
@BuiltValueField(wireName: 'created_at')
|
||||
String? get createdAt;
|
||||
|
||||
@BuiltValueField(wireName: 'updated_at')
|
||||
String? get updatedAt;
|
||||
|
||||
@BuiltValueField(wireName: 'width')
|
||||
int? get width;
|
||||
|
||||
@BuiltValueField(wireName: 'height')
|
||||
int? get height;
|
||||
|
||||
@BuiltValueField(wireName: 'color')
|
||||
String? get color;
|
||||
|
||||
@BuiltValueField(wireName: 'downloads')
|
||||
int? get downloads;
|
||||
|
||||
@BuiltValueField(wireName: 'likes')
|
||||
int? get likes;
|
||||
|
||||
@BuiltValueField(wireName: 'liked_by_user')
|
||||
bool? get likedByUser;
|
||||
|
||||
@BuiltValueField(wireName: 'description')
|
||||
String? get description;
|
||||
|
||||
@BuiltValueField(wireName: 'exif')
|
||||
Exif? get exif;
|
||||
|
||||
@BuiltValueField(wireName: 'location')
|
||||
Location? get location;
|
||||
|
||||
@BuiltValueField(wireName: 'tags')
|
||||
BuiltList<Tags>? get tags;
|
||||
|
||||
@BuiltValueField(wireName: 'current_user_collections')
|
||||
BuiltList<CurrentUserCollections>? get currentUserCollections;
|
||||
|
||||
@BuiltValueField(wireName: 'urls')
|
||||
Urls? get urls;
|
||||
|
||||
@BuiltValueField(wireName: 'links')
|
||||
Links? get links;
|
||||
|
||||
@BuiltValueField(wireName: 'user')
|
||||
User? get user;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Photo.serializer, this));
|
||||
}
|
||||
|
||||
static Photo? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Photo.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Photo> get serializer => _$photoSerializer;
|
||||
}
|
||||
@@ -1,553 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'photo.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Photo> _$photoSerializer = new _$PhotoSerializer();
|
||||
|
||||
class _$PhotoSerializer implements StructuredSerializer<Photo> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Photo, _$Photo];
|
||||
@override
|
||||
final String wireName = 'Photo';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Photo object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'id',
|
||||
serializers.serialize(object.id, specifiedType: const FullType(String)),
|
||||
];
|
||||
Object? value;
|
||||
value = object.createdAt;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('created_at')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.updatedAt;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('updated_at')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.width;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('width')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.height;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('height')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.color;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('color')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.downloads;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('downloads')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.likes;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('likes')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.likedByUser;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('liked_by_user')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(bool)));
|
||||
}
|
||||
value = object.description;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('description')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.exif;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('exif')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(Exif)));
|
||||
}
|
||||
value = object.location;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('location')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(Location)));
|
||||
}
|
||||
value = object.tags;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('tags')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Tags)])));
|
||||
}
|
||||
value = object.currentUserCollections;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('current_user_collections')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(
|
||||
BuiltList, const [const FullType(CurrentUserCollections)])));
|
||||
}
|
||||
value = object.urls;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('urls')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(Urls)));
|
||||
}
|
||||
value = object.links;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('links')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(Links)));
|
||||
}
|
||||
value = object.user;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('user')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(User)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Photo deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new PhotoBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'id':
|
||||
result.id = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'created_at':
|
||||
result.createdAt = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'updated_at':
|
||||
result.updatedAt = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'width':
|
||||
result.width = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'height':
|
||||
result.height = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'color':
|
||||
result.color = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'downloads':
|
||||
result.downloads = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'likes':
|
||||
result.likes = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'liked_by_user':
|
||||
result.likedByUser = serializers.deserialize(value,
|
||||
specifiedType: const FullType(bool)) as bool;
|
||||
break;
|
||||
case 'description':
|
||||
result.description = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'exif':
|
||||
result.exif.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Exif))! as Exif);
|
||||
break;
|
||||
case 'location':
|
||||
result.location.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Location))! as Location);
|
||||
break;
|
||||
case 'tags':
|
||||
result.tags.replace(serializers.deserialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Tags)]))!
|
||||
as BuiltList<Object>);
|
||||
break;
|
||||
case 'current_user_collections':
|
||||
result.currentUserCollections.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(BuiltList, const [
|
||||
const FullType(CurrentUserCollections)
|
||||
]))! as BuiltList<Object>);
|
||||
break;
|
||||
case 'urls':
|
||||
result.urls.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Urls))! as Urls);
|
||||
break;
|
||||
case 'links':
|
||||
result.links.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Links))! as Links);
|
||||
break;
|
||||
case 'user':
|
||||
result.user.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(User))! as User);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Photo extends Photo {
|
||||
@override
|
||||
final String id;
|
||||
@override
|
||||
final String? createdAt;
|
||||
@override
|
||||
final String? updatedAt;
|
||||
@override
|
||||
final int? width;
|
||||
@override
|
||||
final int? height;
|
||||
@override
|
||||
final String? color;
|
||||
@override
|
||||
final int? downloads;
|
||||
@override
|
||||
final int? likes;
|
||||
@override
|
||||
final bool? likedByUser;
|
||||
@override
|
||||
final String? description;
|
||||
@override
|
||||
final Exif? exif;
|
||||
@override
|
||||
final Location? location;
|
||||
@override
|
||||
final BuiltList<Tags>? tags;
|
||||
@override
|
||||
final BuiltList<CurrentUserCollections>? currentUserCollections;
|
||||
@override
|
||||
final Urls? urls;
|
||||
@override
|
||||
final Links? links;
|
||||
@override
|
||||
final User? user;
|
||||
|
||||
factory _$Photo([void Function(PhotoBuilder)? updates]) =>
|
||||
(new PhotoBuilder()..update(updates)).build();
|
||||
|
||||
_$Photo._(
|
||||
{required this.id,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.width,
|
||||
this.height,
|
||||
this.color,
|
||||
this.downloads,
|
||||
this.likes,
|
||||
this.likedByUser,
|
||||
this.description,
|
||||
this.exif,
|
||||
this.location,
|
||||
this.tags,
|
||||
this.currentUserCollections,
|
||||
this.urls,
|
||||
this.links,
|
||||
this.user})
|
||||
: super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(id, 'Photo', 'id');
|
||||
}
|
||||
|
||||
@override
|
||||
Photo rebuild(void Function(PhotoBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
PhotoBuilder toBuilder() => new PhotoBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Photo &&
|
||||
id == other.id &&
|
||||
createdAt == other.createdAt &&
|
||||
updatedAt == other.updatedAt &&
|
||||
width == other.width &&
|
||||
height == other.height &&
|
||||
color == other.color &&
|
||||
downloads == other.downloads &&
|
||||
likes == other.likes &&
|
||||
likedByUser == other.likedByUser &&
|
||||
description == other.description &&
|
||||
exif == other.exif &&
|
||||
location == other.location &&
|
||||
tags == other.tags &&
|
||||
currentUserCollections == other.currentUserCollections &&
|
||||
urls == other.urls &&
|
||||
links == other.links &&
|
||||
user == other.user;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
0,
|
||||
id
|
||||
.hashCode),
|
||||
createdAt
|
||||
.hashCode),
|
||||
updatedAt
|
||||
.hashCode),
|
||||
width.hashCode),
|
||||
height.hashCode),
|
||||
color.hashCode),
|
||||
downloads.hashCode),
|
||||
likes.hashCode),
|
||||
likedByUser.hashCode),
|
||||
description.hashCode),
|
||||
exif.hashCode),
|
||||
location.hashCode),
|
||||
tags.hashCode),
|
||||
currentUserCollections.hashCode),
|
||||
urls.hashCode),
|
||||
links.hashCode),
|
||||
user.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Photo')
|
||||
..add('id', id)
|
||||
..add('createdAt', createdAt)
|
||||
..add('updatedAt', updatedAt)
|
||||
..add('width', width)
|
||||
..add('height', height)
|
||||
..add('color', color)
|
||||
..add('downloads', downloads)
|
||||
..add('likes', likes)
|
||||
..add('likedByUser', likedByUser)
|
||||
..add('description', description)
|
||||
..add('exif', exif)
|
||||
..add('location', location)
|
||||
..add('tags', tags)
|
||||
..add('currentUserCollections', currentUserCollections)
|
||||
..add('urls', urls)
|
||||
..add('links', links)
|
||||
..add('user', user))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class PhotoBuilder implements Builder<Photo, PhotoBuilder> {
|
||||
_$Photo? _$v;
|
||||
|
||||
String? _id;
|
||||
String? get id => _$this._id;
|
||||
set id(String? id) => _$this._id = id;
|
||||
|
||||
String? _createdAt;
|
||||
String? get createdAt => _$this._createdAt;
|
||||
set createdAt(String? createdAt) => _$this._createdAt = createdAt;
|
||||
|
||||
String? _updatedAt;
|
||||
String? get updatedAt => _$this._updatedAt;
|
||||
set updatedAt(String? updatedAt) => _$this._updatedAt = updatedAt;
|
||||
|
||||
int? _width;
|
||||
int? get width => _$this._width;
|
||||
set width(int? width) => _$this._width = width;
|
||||
|
||||
int? _height;
|
||||
int? get height => _$this._height;
|
||||
set height(int? height) => _$this._height = height;
|
||||
|
||||
String? _color;
|
||||
String? get color => _$this._color;
|
||||
set color(String? color) => _$this._color = color;
|
||||
|
||||
int? _downloads;
|
||||
int? get downloads => _$this._downloads;
|
||||
set downloads(int? downloads) => _$this._downloads = downloads;
|
||||
|
||||
int? _likes;
|
||||
int? get likes => _$this._likes;
|
||||
set likes(int? likes) => _$this._likes = likes;
|
||||
|
||||
bool? _likedByUser;
|
||||
bool? get likedByUser => _$this._likedByUser;
|
||||
set likedByUser(bool? likedByUser) => _$this._likedByUser = likedByUser;
|
||||
|
||||
String? _description;
|
||||
String? get description => _$this._description;
|
||||
set description(String? description) => _$this._description = description;
|
||||
|
||||
ExifBuilder? _exif;
|
||||
ExifBuilder get exif => _$this._exif ??= new ExifBuilder();
|
||||
set exif(ExifBuilder? exif) => _$this._exif = exif;
|
||||
|
||||
LocationBuilder? _location;
|
||||
LocationBuilder get location => _$this._location ??= new LocationBuilder();
|
||||
set location(LocationBuilder? location) => _$this._location = location;
|
||||
|
||||
ListBuilder<Tags>? _tags;
|
||||
ListBuilder<Tags> get tags => _$this._tags ??= new ListBuilder<Tags>();
|
||||
set tags(ListBuilder<Tags>? tags) => _$this._tags = tags;
|
||||
|
||||
ListBuilder<CurrentUserCollections>? _currentUserCollections;
|
||||
ListBuilder<CurrentUserCollections> get currentUserCollections =>
|
||||
_$this._currentUserCollections ??=
|
||||
new ListBuilder<CurrentUserCollections>();
|
||||
set currentUserCollections(
|
||||
ListBuilder<CurrentUserCollections>? currentUserCollections) =>
|
||||
_$this._currentUserCollections = currentUserCollections;
|
||||
|
||||
UrlsBuilder? _urls;
|
||||
UrlsBuilder get urls => _$this._urls ??= new UrlsBuilder();
|
||||
set urls(UrlsBuilder? urls) => _$this._urls = urls;
|
||||
|
||||
LinksBuilder? _links;
|
||||
LinksBuilder get links => _$this._links ??= new LinksBuilder();
|
||||
set links(LinksBuilder? links) => _$this._links = links;
|
||||
|
||||
UserBuilder? _user;
|
||||
UserBuilder get user => _$this._user ??= new UserBuilder();
|
||||
set user(UserBuilder? user) => _$this._user = user;
|
||||
|
||||
PhotoBuilder();
|
||||
|
||||
PhotoBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_id = $v.id;
|
||||
_createdAt = $v.createdAt;
|
||||
_updatedAt = $v.updatedAt;
|
||||
_width = $v.width;
|
||||
_height = $v.height;
|
||||
_color = $v.color;
|
||||
_downloads = $v.downloads;
|
||||
_likes = $v.likes;
|
||||
_likedByUser = $v.likedByUser;
|
||||
_description = $v.description;
|
||||
_exif = $v.exif?.toBuilder();
|
||||
_location = $v.location?.toBuilder();
|
||||
_tags = $v.tags?.toBuilder();
|
||||
_currentUserCollections = $v.currentUserCollections?.toBuilder();
|
||||
_urls = $v.urls?.toBuilder();
|
||||
_links = $v.links?.toBuilder();
|
||||
_user = $v.user?.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Photo other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Photo;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(PhotoBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Photo build() {
|
||||
_$Photo _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$Photo._(
|
||||
id: BuiltValueNullFieldError.checkNotNull(id, 'Photo', 'id'),
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
width: width,
|
||||
height: height,
|
||||
color: color,
|
||||
downloads: downloads,
|
||||
likes: likes,
|
||||
likedByUser: likedByUser,
|
||||
description: description,
|
||||
exif: _exif?.build(),
|
||||
location: _location?.build(),
|
||||
tags: _tags?.build(),
|
||||
currentUserCollections: _currentUserCollections?.build(),
|
||||
urls: _urls?.build(),
|
||||
links: _links?.build(),
|
||||
user: _user?.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'exif';
|
||||
_exif?.build();
|
||||
_$failedField = 'location';
|
||||
_location?.build();
|
||||
_$failedField = 'tags';
|
||||
_tags?.build();
|
||||
_$failedField = 'currentUserCollections';
|
||||
_currentUserCollections?.build();
|
||||
_$failedField = 'urls';
|
||||
_urls?.build();
|
||||
_$failedField = 'links';
|
||||
_links?.build();
|
||||
_$failedField = 'user';
|
||||
_user?.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'Photo', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,35 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'position.g.dart';
|
||||
|
||||
abstract class Position implements Built<Position, PositionBuilder> {
|
||||
factory Position([void Function(PositionBuilder)? updates]) = _$Position;
|
||||
|
||||
Position._();
|
||||
|
||||
@BuiltValueField(wireName: 'latitude')
|
||||
double get latitude;
|
||||
|
||||
@BuiltValueField(wireName: 'longitude')
|
||||
double get longitude;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Position.serializer, this));
|
||||
}
|
||||
|
||||
static Position? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Position.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Position> get serializer => _$positionSerializer;
|
||||
}
|
||||
@@ -1,152 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'position.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Position> _$positionSerializer = new _$PositionSerializer();
|
||||
|
||||
class _$PositionSerializer implements StructuredSerializer<Position> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Position, _$Position];
|
||||
@override
|
||||
final String wireName = 'Position';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Position object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'latitude',
|
||||
serializers.serialize(object.latitude,
|
||||
specifiedType: const FullType(double)),
|
||||
'longitude',
|
||||
serializers.serialize(object.longitude,
|
||||
specifiedType: const FullType(double)),
|
||||
];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Position deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new PositionBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'latitude':
|
||||
result.latitude = serializers.deserialize(value,
|
||||
specifiedType: const FullType(double)) as double;
|
||||
break;
|
||||
case 'longitude':
|
||||
result.longitude = serializers.deserialize(value,
|
||||
specifiedType: const FullType(double)) as double;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Position extends Position {
|
||||
@override
|
||||
final double latitude;
|
||||
@override
|
||||
final double longitude;
|
||||
|
||||
factory _$Position([void Function(PositionBuilder)? updates]) =>
|
||||
(new PositionBuilder()..update(updates)).build();
|
||||
|
||||
_$Position._({required this.latitude, required this.longitude}) : super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(latitude, 'Position', 'latitude');
|
||||
BuiltValueNullFieldError.checkNotNull(longitude, 'Position', 'longitude');
|
||||
}
|
||||
|
||||
@override
|
||||
Position rebuild(void Function(PositionBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
PositionBuilder toBuilder() => new PositionBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Position &&
|
||||
latitude == other.latitude &&
|
||||
longitude == other.longitude;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc($jc(0, latitude.hashCode), longitude.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Position')
|
||||
..add('latitude', latitude)
|
||||
..add('longitude', longitude))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class PositionBuilder implements Builder<Position, PositionBuilder> {
|
||||
_$Position? _$v;
|
||||
|
||||
double? _latitude;
|
||||
double? get latitude => _$this._latitude;
|
||||
set latitude(double? latitude) => _$this._latitude = latitude;
|
||||
|
||||
double? _longitude;
|
||||
double? get longitude => _$this._longitude;
|
||||
set longitude(double? longitude) => _$this._longitude = longitude;
|
||||
|
||||
PositionBuilder();
|
||||
|
||||
PositionBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_latitude = $v.latitude;
|
||||
_longitude = $v.longitude;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Position other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Position;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(PositionBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Position build() {
|
||||
final _$result = _$v ??
|
||||
new _$Position._(
|
||||
latitude: BuiltValueNullFieldError.checkNotNull(
|
||||
latitude, 'Position', 'latitude'),
|
||||
longitude: BuiltValueNullFieldError.checkNotNull(
|
||||
longitude, 'Position', 'longitude'));
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,45 +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 'dart:convert';
|
||||
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
import 'photo.dart';
|
||||
|
||||
part 'search_photos_response.g.dart';
|
||||
|
||||
abstract class SearchPhotosResponse
|
||||
implements Built<SearchPhotosResponse, SearchPhotosResponseBuilder> {
|
||||
factory SearchPhotosResponse(
|
||||
[void Function(SearchPhotosResponseBuilder)? updates]) =
|
||||
_$SearchPhotosResponse;
|
||||
|
||||
SearchPhotosResponse._();
|
||||
|
||||
@BuiltValueField(wireName: 'total')
|
||||
int? get total;
|
||||
|
||||
@BuiltValueField(wireName: 'total_pages')
|
||||
int? get totalPages;
|
||||
|
||||
@BuiltValueField(wireName: 'results')
|
||||
BuiltList<Photo> get results;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(
|
||||
serializers.serializeWith(SearchPhotosResponse.serializer, this));
|
||||
}
|
||||
|
||||
static SearchPhotosResponse? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
SearchPhotosResponse.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<SearchPhotosResponse> get serializer =>
|
||||
_$searchPhotosResponseSerializer;
|
||||
}
|
||||
@@ -1,201 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'search_photos_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<SearchPhotosResponse> _$searchPhotosResponseSerializer =
|
||||
new _$SearchPhotosResponseSerializer();
|
||||
|
||||
class _$SearchPhotosResponseSerializer
|
||||
implements StructuredSerializer<SearchPhotosResponse> {
|
||||
@override
|
||||
final Iterable<Type> types = const [
|
||||
SearchPhotosResponse,
|
||||
_$SearchPhotosResponse
|
||||
];
|
||||
@override
|
||||
final String wireName = 'SearchPhotosResponse';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(
|
||||
Serializers serializers, SearchPhotosResponse object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'results',
|
||||
serializers.serialize(object.results,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Photo)])),
|
||||
];
|
||||
Object? value;
|
||||
value = object.total;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('total')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.totalPages;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('total_pages')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
SearchPhotosResponse deserialize(
|
||||
Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new SearchPhotosResponseBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'total':
|
||||
result.total = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'total_pages':
|
||||
result.totalPages = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'results':
|
||||
result.results.replace(serializers.deserialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(Photo)]))!
|
||||
as BuiltList<Object>);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$SearchPhotosResponse extends SearchPhotosResponse {
|
||||
@override
|
||||
final int? total;
|
||||
@override
|
||||
final int? totalPages;
|
||||
@override
|
||||
final BuiltList<Photo> results;
|
||||
|
||||
factory _$SearchPhotosResponse(
|
||||
[void Function(SearchPhotosResponseBuilder)? updates]) =>
|
||||
(new SearchPhotosResponseBuilder()..update(updates)).build();
|
||||
|
||||
_$SearchPhotosResponse._({this.total, this.totalPages, required this.results})
|
||||
: super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(
|
||||
results, 'SearchPhotosResponse', 'results');
|
||||
}
|
||||
|
||||
@override
|
||||
SearchPhotosResponse rebuild(
|
||||
void Function(SearchPhotosResponseBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
SearchPhotosResponseBuilder toBuilder() =>
|
||||
new SearchPhotosResponseBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is SearchPhotosResponse &&
|
||||
total == other.total &&
|
||||
totalPages == other.totalPages &&
|
||||
results == other.results;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc($jc(0, total.hashCode), totalPages.hashCode), results.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('SearchPhotosResponse')
|
||||
..add('total', total)
|
||||
..add('totalPages', totalPages)
|
||||
..add('results', results))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class SearchPhotosResponseBuilder
|
||||
implements Builder<SearchPhotosResponse, SearchPhotosResponseBuilder> {
|
||||
_$SearchPhotosResponse? _$v;
|
||||
|
||||
int? _total;
|
||||
int? get total => _$this._total;
|
||||
set total(int? total) => _$this._total = total;
|
||||
|
||||
int? _totalPages;
|
||||
int? get totalPages => _$this._totalPages;
|
||||
set totalPages(int? totalPages) => _$this._totalPages = totalPages;
|
||||
|
||||
ListBuilder<Photo>? _results;
|
||||
ListBuilder<Photo> get results =>
|
||||
_$this._results ??= new ListBuilder<Photo>();
|
||||
set results(ListBuilder<Photo>? results) => _$this._results = results;
|
||||
|
||||
SearchPhotosResponseBuilder();
|
||||
|
||||
SearchPhotosResponseBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_total = $v.total;
|
||||
_totalPages = $v.totalPages;
|
||||
_results = $v.results.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(SearchPhotosResponse other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$SearchPhotosResponse;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(SearchPhotosResponseBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$SearchPhotosResponse build() {
|
||||
_$SearchPhotosResponse _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$SearchPhotosResponse._(
|
||||
total: total, totalPages: totalPages, results: results.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'results';
|
||||
results.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'SearchPhotosResponse', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,32 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'tags.g.dart';
|
||||
|
||||
abstract class Tags implements Built<Tags, TagsBuilder> {
|
||||
factory Tags([void Function(TagsBuilder)? updates]) = _$Tags;
|
||||
|
||||
Tags._();
|
||||
|
||||
@BuiltValueField(wireName: 'title')
|
||||
String get title;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Tags.serializer, this));
|
||||
}
|
||||
|
||||
static Tags? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Tags.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Tags> get serializer => _$tagsSerializer;
|
||||
}
|
||||
@@ -1,131 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'tags.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Tags> _$tagsSerializer = new _$TagsSerializer();
|
||||
|
||||
class _$TagsSerializer implements StructuredSerializer<Tags> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Tags, _$Tags];
|
||||
@override
|
||||
final String wireName = 'Tags';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Tags object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'title',
|
||||
serializers.serialize(object.title,
|
||||
specifiedType: const FullType(String)),
|
||||
];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Tags deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new TagsBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'title':
|
||||
result.title = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Tags extends Tags {
|
||||
@override
|
||||
final String title;
|
||||
|
||||
factory _$Tags([void Function(TagsBuilder)? updates]) =>
|
||||
(new TagsBuilder()..update(updates)).build();
|
||||
|
||||
_$Tags._({required this.title}) : super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(title, 'Tags', 'title');
|
||||
}
|
||||
|
||||
@override
|
||||
Tags rebuild(void Function(TagsBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
TagsBuilder toBuilder() => new TagsBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Tags && title == other.title;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(0, title.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Tags')..add('title', title))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class TagsBuilder implements Builder<Tags, TagsBuilder> {
|
||||
_$Tags? _$v;
|
||||
|
||||
String? _title;
|
||||
String? get title => _$this._title;
|
||||
set title(String? title) => _$this._title = title;
|
||||
|
||||
TagsBuilder();
|
||||
|
||||
TagsBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_title = $v.title;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Tags other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Tags;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(TagsBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Tags build() {
|
||||
final _$result = _$v ??
|
||||
new _$Tags._(
|
||||
title:
|
||||
BuiltValueNullFieldError.checkNotNull(title, 'Tags', 'title'));
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,118 +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 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'api_error.dart';
|
||||
import 'photo.dart';
|
||||
import 'search_photos_response.dart';
|
||||
|
||||
final _unsplashBaseUrl = Uri.parse('https://api.unsplash.com/');
|
||||
|
||||
/// Unsplash API Client. Requires an
|
||||
/// [Unsplash API](https://unsplash.com/developers) `accessKey` to make
|
||||
/// requests to the Unsplash API.
|
||||
class Unsplash {
|
||||
Unsplash({
|
||||
required String accessKey,
|
||||
http.BaseClient? httpClient,
|
||||
}) : _accessKey = accessKey,
|
||||
_client = httpClient ?? http.Client();
|
||||
|
||||
final String _accessKey;
|
||||
final http.Client _client;
|
||||
final _log = Logger('Unsplash');
|
||||
|
||||
Future<SearchPhotosResponse?> searchPhotos({
|
||||
required String query,
|
||||
num page = 1,
|
||||
num perPage = 10,
|
||||
List<num> collections = const [],
|
||||
SearchPhotosOrientation? orientation,
|
||||
}) async {
|
||||
final searchPhotosUrl = _unsplashBaseUrl
|
||||
.replace(path: '/search/photos', queryParameters: <String, String>{
|
||||
'query': query,
|
||||
if (page != 1) 'page': '$page',
|
||||
if (perPage != 10) 'per_page': '$perPage',
|
||||
if (collections.isNotEmpty) 'collections': collections.join(','),
|
||||
if (orientation == SearchPhotosOrientation.landscape)
|
||||
'orientation': 'landscape',
|
||||
if (orientation == SearchPhotosOrientation.portrait)
|
||||
'orientation': 'portrait',
|
||||
if (orientation == SearchPhotosOrientation.squarish)
|
||||
'orientation': 'squarish',
|
||||
});
|
||||
_log.info('GET $searchPhotosUrl');
|
||||
|
||||
final response = await _client.get(
|
||||
searchPhotosUrl,
|
||||
headers: {
|
||||
'Accept-Version': 'v1',
|
||||
'Authorization': 'Client-ID $_accessKey',
|
||||
},
|
||||
);
|
||||
|
||||
dynamic body;
|
||||
try {
|
||||
body = json.fuse(utf8).decode(response.bodyBytes);
|
||||
} catch (e) {
|
||||
throw UnsplashException('Invalid JSON received');
|
||||
}
|
||||
|
||||
if (body is Map &&
|
||||
body['errors'] is List &&
|
||||
body['errors'].isNotEmpty as bool) {
|
||||
final apiError = ApiError.fromJson(response.body)!;
|
||||
throw UnsplashException(apiError.errors!.join(', '));
|
||||
}
|
||||
|
||||
return SearchPhotosResponse.fromJson(
|
||||
response.body,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Uint8List> download(Photo photo) async {
|
||||
// For detail on how downloading photos from Unsplash, please see
|
||||
// https://help.unsplash.com/en/articles/2511258-guideline-triggering-a-download
|
||||
|
||||
_log.info('GET ${photo.urls!.full}');
|
||||
final futureBytes = http.readBytes(Uri.parse(photo.urls!.full!), headers: {
|
||||
'Accept-Version': 'v1',
|
||||
'Authorization': 'Client-ID $_accessKey',
|
||||
});
|
||||
|
||||
_log.info('GET ${photo.links!.downloadLocation}');
|
||||
http.get(Uri.parse(photo.links!.downloadLocation!), headers: {
|
||||
'Accept-Version': 'v1',
|
||||
'Authorization': 'Client-ID $_accessKey',
|
||||
});
|
||||
|
||||
return futureBytes;
|
||||
}
|
||||
}
|
||||
|
||||
enum SearchPhotosOrientation {
|
||||
landscape,
|
||||
portrait,
|
||||
squarish,
|
||||
}
|
||||
|
||||
class UnsplashException implements Exception {
|
||||
UnsplashException([this.message]);
|
||||
|
||||
final String? message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (message == null) {
|
||||
return 'UnsplashException';
|
||||
}
|
||||
return 'UnsplashException: $message';
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
|
||||
part 'urls.g.dart';
|
||||
|
||||
abstract class Urls implements Built<Urls, UrlsBuilder> {
|
||||
factory Urls([void Function(UrlsBuilder b)? updates]) = _$Urls;
|
||||
|
||||
Urls._();
|
||||
|
||||
@BuiltValueField(wireName: 'raw')
|
||||
String? get raw;
|
||||
|
||||
@BuiltValueField(wireName: 'full')
|
||||
String? get full;
|
||||
|
||||
@BuiltValueField(wireName: 'regular')
|
||||
String? get regular;
|
||||
|
||||
@BuiltValueField(wireName: 'small')
|
||||
String? get small;
|
||||
|
||||
@BuiltValueField(wireName: 'thumb')
|
||||
String? get thumb;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(Urls.serializer, this));
|
||||
}
|
||||
|
||||
static Urls? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
Urls.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<Urls> get serializer => _$urlsSerializer;
|
||||
}
|
||||
@@ -1,217 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'urls.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<Urls> _$urlsSerializer = new _$UrlsSerializer();
|
||||
|
||||
class _$UrlsSerializer implements StructuredSerializer<Urls> {
|
||||
@override
|
||||
final Iterable<Type> types = const [Urls, _$Urls];
|
||||
@override
|
||||
final String wireName = 'Urls';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, Urls object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[];
|
||||
Object? value;
|
||||
value = object.raw;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('raw')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.full;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('full')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.regular;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('regular')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.small;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('small')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.thumb;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('thumb')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Urls deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new UrlsBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'raw':
|
||||
result.raw = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'full':
|
||||
result.full = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'regular':
|
||||
result.regular = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'small':
|
||||
result.small = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'thumb':
|
||||
result.thumb = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$Urls extends Urls {
|
||||
@override
|
||||
final String? raw;
|
||||
@override
|
||||
final String? full;
|
||||
@override
|
||||
final String? regular;
|
||||
@override
|
||||
final String? small;
|
||||
@override
|
||||
final String? thumb;
|
||||
|
||||
factory _$Urls([void Function(UrlsBuilder)? updates]) =>
|
||||
(new UrlsBuilder()..update(updates)).build();
|
||||
|
||||
_$Urls._({this.raw, this.full, this.regular, this.small, this.thumb})
|
||||
: super._();
|
||||
|
||||
@override
|
||||
Urls rebuild(void Function(UrlsBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
UrlsBuilder toBuilder() => new UrlsBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is Urls &&
|
||||
raw == other.raw &&
|
||||
full == other.full &&
|
||||
regular == other.regular &&
|
||||
small == other.small &&
|
||||
thumb == other.thumb;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc($jc($jc($jc(0, raw.hashCode), full.hashCode), regular.hashCode),
|
||||
small.hashCode),
|
||||
thumb.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('Urls')
|
||||
..add('raw', raw)
|
||||
..add('full', full)
|
||||
..add('regular', regular)
|
||||
..add('small', small)
|
||||
..add('thumb', thumb))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class UrlsBuilder implements Builder<Urls, UrlsBuilder> {
|
||||
_$Urls? _$v;
|
||||
|
||||
String? _raw;
|
||||
String? get raw => _$this._raw;
|
||||
set raw(String? raw) => _$this._raw = raw;
|
||||
|
||||
String? _full;
|
||||
String? get full => _$this._full;
|
||||
set full(String? full) => _$this._full = full;
|
||||
|
||||
String? _regular;
|
||||
String? get regular => _$this._regular;
|
||||
set regular(String? regular) => _$this._regular = regular;
|
||||
|
||||
String? _small;
|
||||
String? get small => _$this._small;
|
||||
set small(String? small) => _$this._small = small;
|
||||
|
||||
String? _thumb;
|
||||
String? get thumb => _$this._thumb;
|
||||
set thumb(String? thumb) => _$this._thumb = thumb;
|
||||
|
||||
UrlsBuilder();
|
||||
|
||||
UrlsBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_raw = $v.raw;
|
||||
_full = $v.full;
|
||||
_regular = $v.regular;
|
||||
_small = $v.small;
|
||||
_thumb = $v.thumb;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(Urls other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$Urls;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(UrlsBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$Urls build() {
|
||||
final _$result = _$v ??
|
||||
new _$Urls._(
|
||||
raw: raw, full: full, regular: regular, small: small, thumb: thumb);
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,63 +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 'dart:convert';
|
||||
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
|
||||
import '../serializers.dart';
|
||||
import 'links.dart';
|
||||
|
||||
part 'user.g.dart';
|
||||
|
||||
abstract class User implements Built<User, UserBuilder> {
|
||||
factory User([void Function(UserBuilder)? updates]) = _$User;
|
||||
|
||||
User._();
|
||||
|
||||
@BuiltValueField(wireName: 'id')
|
||||
String get id;
|
||||
|
||||
@BuiltValueField(wireName: 'updated_at')
|
||||
String? get updatedAt;
|
||||
|
||||
@BuiltValueField(wireName: 'username')
|
||||
String get username;
|
||||
|
||||
@BuiltValueField(wireName: 'name')
|
||||
String get name;
|
||||
|
||||
@BuiltValueField(wireName: 'portfolio_url')
|
||||
String? get portfolioUrl;
|
||||
|
||||
@BuiltValueField(wireName: 'bio')
|
||||
String? get bio;
|
||||
|
||||
@BuiltValueField(wireName: 'location')
|
||||
String? get location;
|
||||
|
||||
@BuiltValueField(wireName: 'total_likes')
|
||||
int? get totalLikes;
|
||||
|
||||
@BuiltValueField(wireName: 'total_photos')
|
||||
int? get totalPhotos;
|
||||
|
||||
@BuiltValueField(wireName: 'total_collections')
|
||||
int? get totalCollections;
|
||||
|
||||
@BuiltValueField(wireName: 'links')
|
||||
Links? get links;
|
||||
|
||||
String toJson() {
|
||||
return json.encode(serializers.serializeWith(User.serializer, this));
|
||||
}
|
||||
|
||||
static User? fromJson(String jsonString) {
|
||||
return serializers.deserializeWith(
|
||||
User.serializer, json.decode(jsonString));
|
||||
}
|
||||
|
||||
static Serializer<User> get serializer => _$userSerializer;
|
||||
}
|
||||
@@ -1,377 +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.
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// BuiltValueGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Serializer<User> _$userSerializer = new _$UserSerializer();
|
||||
|
||||
class _$UserSerializer implements StructuredSerializer<User> {
|
||||
@override
|
||||
final Iterable<Type> types = const [User, _$User];
|
||||
@override
|
||||
final String wireName = 'User';
|
||||
|
||||
@override
|
||||
Iterable<Object?> serialize(Serializers serializers, User object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object?>[
|
||||
'id',
|
||||
serializers.serialize(object.id, specifiedType: const FullType(String)),
|
||||
'username',
|
||||
serializers.serialize(object.username,
|
||||
specifiedType: const FullType(String)),
|
||||
'name',
|
||||
serializers.serialize(object.name, specifiedType: const FullType(String)),
|
||||
];
|
||||
Object? value;
|
||||
value = object.updatedAt;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('updated_at')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.portfolioUrl;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('portfolio_url')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.bio;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('bio')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.location;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('location')
|
||||
..add(serializers.serialize(value,
|
||||
specifiedType: const FullType(String)));
|
||||
}
|
||||
value = object.totalLikes;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('total_likes')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.totalPhotos;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('total_photos')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.totalCollections;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('total_collections')
|
||||
..add(serializers.serialize(value, specifiedType: const FullType(int)));
|
||||
}
|
||||
value = object.links;
|
||||
if (value != null) {
|
||||
result
|
||||
..add('links')
|
||||
..add(
|
||||
serializers.serialize(value, specifiedType: const FullType(Links)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
User deserialize(Serializers serializers, Iterable<Object?> serialized,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = new UserBuilder();
|
||||
|
||||
final iterator = serialized.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
final key = iterator.current as String;
|
||||
iterator.moveNext();
|
||||
final Object? value = iterator.current;
|
||||
switch (key) {
|
||||
case 'id':
|
||||
result.id = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'updated_at':
|
||||
result.updatedAt = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'username':
|
||||
result.username = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'name':
|
||||
result.name = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'portfolio_url':
|
||||
result.portfolioUrl = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'bio':
|
||||
result.bio = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'location':
|
||||
result.location = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'total_likes':
|
||||
result.totalLikes = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'total_photos':
|
||||
result.totalPhotos = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'total_collections':
|
||||
result.totalCollections = serializers.deserialize(value,
|
||||
specifiedType: const FullType(int)) as int;
|
||||
break;
|
||||
case 'links':
|
||||
result.links.replace(serializers.deserialize(value,
|
||||
specifiedType: const FullType(Links))! as Links);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
class _$User extends User {
|
||||
@override
|
||||
final String id;
|
||||
@override
|
||||
final String? updatedAt;
|
||||
@override
|
||||
final String username;
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final String? portfolioUrl;
|
||||
@override
|
||||
final String? bio;
|
||||
@override
|
||||
final String? location;
|
||||
@override
|
||||
final int? totalLikes;
|
||||
@override
|
||||
final int? totalPhotos;
|
||||
@override
|
||||
final int? totalCollections;
|
||||
@override
|
||||
final Links? links;
|
||||
|
||||
factory _$User([void Function(UserBuilder)? updates]) =>
|
||||
(new UserBuilder()..update(updates)).build();
|
||||
|
||||
_$User._(
|
||||
{required this.id,
|
||||
this.updatedAt,
|
||||
required this.username,
|
||||
required this.name,
|
||||
this.portfolioUrl,
|
||||
this.bio,
|
||||
this.location,
|
||||
this.totalLikes,
|
||||
this.totalPhotos,
|
||||
this.totalCollections,
|
||||
this.links})
|
||||
: super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(id, 'User', 'id');
|
||||
BuiltValueNullFieldError.checkNotNull(username, 'User', 'username');
|
||||
BuiltValueNullFieldError.checkNotNull(name, 'User', 'name');
|
||||
}
|
||||
|
||||
@override
|
||||
User rebuild(void Function(UserBuilder) updates) =>
|
||||
(toBuilder()..update(updates)).build();
|
||||
|
||||
@override
|
||||
UserBuilder toBuilder() => new UserBuilder()..replace(this);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(other, this)) return true;
|
||||
return other is User &&
|
||||
id == other.id &&
|
||||
updatedAt == other.updatedAt &&
|
||||
username == other.username &&
|
||||
name == other.name &&
|
||||
portfolioUrl == other.portfolioUrl &&
|
||||
bio == other.bio &&
|
||||
location == other.location &&
|
||||
totalLikes == other.totalLikes &&
|
||||
totalPhotos == other.totalPhotos &&
|
||||
totalCollections == other.totalCollections &&
|
||||
links == other.links;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc($jc(0, id.hashCode),
|
||||
updatedAt.hashCode),
|
||||
username.hashCode),
|
||||
name.hashCode),
|
||||
portfolioUrl.hashCode),
|
||||
bio.hashCode),
|
||||
location.hashCode),
|
||||
totalLikes.hashCode),
|
||||
totalPhotos.hashCode),
|
||||
totalCollections.hashCode),
|
||||
links.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('User')
|
||||
..add('id', id)
|
||||
..add('updatedAt', updatedAt)
|
||||
..add('username', username)
|
||||
..add('name', name)
|
||||
..add('portfolioUrl', portfolioUrl)
|
||||
..add('bio', bio)
|
||||
..add('location', location)
|
||||
..add('totalLikes', totalLikes)
|
||||
..add('totalPhotos', totalPhotos)
|
||||
..add('totalCollections', totalCollections)
|
||||
..add('links', links))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class UserBuilder implements Builder<User, UserBuilder> {
|
||||
_$User? _$v;
|
||||
|
||||
String? _id;
|
||||
String? get id => _$this._id;
|
||||
set id(String? id) => _$this._id = id;
|
||||
|
||||
String? _updatedAt;
|
||||
String? get updatedAt => _$this._updatedAt;
|
||||
set updatedAt(String? updatedAt) => _$this._updatedAt = updatedAt;
|
||||
|
||||
String? _username;
|
||||
String? get username => _$this._username;
|
||||
set username(String? username) => _$this._username = username;
|
||||
|
||||
String? _name;
|
||||
String? get name => _$this._name;
|
||||
set name(String? name) => _$this._name = name;
|
||||
|
||||
String? _portfolioUrl;
|
||||
String? get portfolioUrl => _$this._portfolioUrl;
|
||||
set portfolioUrl(String? portfolioUrl) => _$this._portfolioUrl = portfolioUrl;
|
||||
|
||||
String? _bio;
|
||||
String? get bio => _$this._bio;
|
||||
set bio(String? bio) => _$this._bio = bio;
|
||||
|
||||
String? _location;
|
||||
String? get location => _$this._location;
|
||||
set location(String? location) => _$this._location = location;
|
||||
|
||||
int? _totalLikes;
|
||||
int? get totalLikes => _$this._totalLikes;
|
||||
set totalLikes(int? totalLikes) => _$this._totalLikes = totalLikes;
|
||||
|
||||
int? _totalPhotos;
|
||||
int? get totalPhotos => _$this._totalPhotos;
|
||||
set totalPhotos(int? totalPhotos) => _$this._totalPhotos = totalPhotos;
|
||||
|
||||
int? _totalCollections;
|
||||
int? get totalCollections => _$this._totalCollections;
|
||||
set totalCollections(int? totalCollections) =>
|
||||
_$this._totalCollections = totalCollections;
|
||||
|
||||
LinksBuilder? _links;
|
||||
LinksBuilder get links => _$this._links ??= new LinksBuilder();
|
||||
set links(LinksBuilder? links) => _$this._links = links;
|
||||
|
||||
UserBuilder();
|
||||
|
||||
UserBuilder get _$this {
|
||||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_id = $v.id;
|
||||
_updatedAt = $v.updatedAt;
|
||||
_username = $v.username;
|
||||
_name = $v.name;
|
||||
_portfolioUrl = $v.portfolioUrl;
|
||||
_bio = $v.bio;
|
||||
_location = $v.location;
|
||||
_totalLikes = $v.totalLikes;
|
||||
_totalPhotos = $v.totalPhotos;
|
||||
_totalCollections = $v.totalCollections;
|
||||
_links = $v.links?.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
void replace(User other) {
|
||||
ArgumentError.checkNotNull(other, 'other');
|
||||
_$v = other as _$User;
|
||||
}
|
||||
|
||||
@override
|
||||
void update(void Function(UserBuilder)? updates) {
|
||||
if (updates != null) updates(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_$User build() {
|
||||
_$User _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$User._(
|
||||
id: BuiltValueNullFieldError.checkNotNull(id, 'User', 'id'),
|
||||
updatedAt: updatedAt,
|
||||
username: BuiltValueNullFieldError.checkNotNull(
|
||||
username, 'User', 'username'),
|
||||
name: BuiltValueNullFieldError.checkNotNull(name, 'User', 'name'),
|
||||
portfolioUrl: portfolioUrl,
|
||||
bio: bio,
|
||||
location: location,
|
||||
totalLikes: totalLikes,
|
||||
totalPhotos: totalPhotos,
|
||||
totalCollections: totalCollections,
|
||||
links: _links?.build());
|
||||
} catch (_) {
|
||||
late String _$failedField;
|
||||
try {
|
||||
_$failedField = 'links';
|
||||
_links?.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'User', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -1,102 +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/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart' as url_launcher;
|
||||
|
||||
class PolicyDialog extends StatelessWidget {
|
||||
const PolicyDialog({
|
||||
Key? key,
|
||||
this.radius = 8,
|
||||
}) : super(key: key);
|
||||
|
||||
final double radius;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)),
|
||||
content: Builder(
|
||||
builder: (context) {
|
||||
var height = MediaQuery.of(context).size.height;
|
||||
var width = MediaQuery.of(context).size.width;
|
||||
return SizedBox(
|
||||
height: height / 4,
|
||||
width: width / 4,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
text: 'Terms & Conditions:\n',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
textAlign: TextAlign.left,
|
||||
text: TextSpan(
|
||||
text: '• ',
|
||||
style: const TextStyle(color: Colors.black, fontSize: 18),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'https://policies.google.com/terms',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.lightBlue),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
const url = 'https://policies.google.com/terms';
|
||||
if (await url_launcher.canLaunch(url)) {
|
||||
await url_launcher.launch(url);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
textAlign: TextAlign.left,
|
||||
text: TextSpan(
|
||||
text: '• ',
|
||||
style: const TextStyle(color: Colors.black, fontSize: 18),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'https://unsplash.com/terms',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.lightBlue),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
const url = 'https://unsplash.com/terms';
|
||||
if (await url_launcher.canLaunch(url)) {
|
||||
await url_launcher.launch(url);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
'CLOSE'.toUpperCase(),
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,113 +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:transparent_image/transparent_image.dart';
|
||||
import 'package:url_launcher/link.dart';
|
||||
|
||||
import '../../unsplash_access_key.dart';
|
||||
import '../unsplash/photo.dart';
|
||||
|
||||
final _unsplashHomepage = Uri.parse(
|
||||
'https://unsplash.com/?utm_source=$unsplashAppName&utm_medium=referral');
|
||||
|
||||
typedef PhotoDetailsPhotoSaveCallback = void Function(Photo);
|
||||
|
||||
class PhotoDetails extends StatefulWidget {
|
||||
const PhotoDetails({
|
||||
required this.photo,
|
||||
required this.onPhotoSave,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
final Photo photo;
|
||||
final PhotoDetailsPhotoSaveCallback onPhotoSave;
|
||||
|
||||
@override
|
||||
_PhotoDetailsState createState() => _PhotoDetailsState();
|
||||
}
|
||||
|
||||
class _PhotoDetailsState extends State<PhotoDetails> {
|
||||
Widget _buildPhotoAttribution(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
const Text('Photo by '),
|
||||
Link(
|
||||
uri: Uri.parse(
|
||||
'https://unsplash.com/@${widget.photo.user!.username}?utm_source=$unsplashAppName&utm_medium=referral'),
|
||||
builder: (context, followLink) => TextButton(
|
||||
onPressed: followLink,
|
||||
child: Text(widget.photo.user!.name),
|
||||
),
|
||||
),
|
||||
const Text(' on '),
|
||||
Link(
|
||||
uri: _unsplashHomepage,
|
||||
builder: (context, followLink) => TextButton(
|
||||
onPressed: followLink,
|
||||
child: const Text('Unsplash'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scrollbar(
|
||||
child: SingleChildScrollView(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Card(
|
||||
shape: ContinuousRectangleBorder(
|
||||
side: const BorderSide(color: Colors.black12),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: AnimatedSize(
|
||||
duration: const Duration(milliseconds: 750),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 40),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 400,
|
||||
minHeight: 400,
|
||||
),
|
||||
child: FadeInImage.memoryNetwork(
|
||||
placeholder: kTransparentImage,
|
||||
imageSemanticLabel: widget.photo.description,
|
||||
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(
|
||||
tooltip: 'Download',
|
||||
visualDensity: VisualDensity.compact,
|
||||
icon: const Icon(Icons.cloud_download),
|
||||
onPressed: () => widget.onPhotoSave(widget.photo),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 48),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +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';
|
||||
|
||||
typedef PhotoSearchDialogCallback = void Function(String searchQuery);
|
||||
|
||||
class PhotoSearchDialog extends StatefulWidget {
|
||||
const PhotoSearchDialog({required this.callback, Key? key}) : super(key: key);
|
||||
final PhotoSearchDialogCallback callback;
|
||||
@override
|
||||
State<PhotoSearchDialog> createState() => _PhotoSearchDialogState();
|
||||
}
|
||||
|
||||
class _PhotoSearchDialogState extends State<PhotoSearchDialog> {
|
||||
final _controller = TextEditingController();
|
||||
bool _searchEnabled = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller.addListener(() {
|
||||
setState(() {
|
||||
_searchEnabled = _controller.text.isNotEmpty;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => AlertDialog(
|
||||
title: const Text('Photo Search'),
|
||||
content: TextField(
|
||||
autofocus: true,
|
||||
controller: _controller,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Search query',
|
||||
),
|
||||
onSubmitted: (content) {
|
||||
if (content.isNotEmpty) {
|
||||
widget.callback(content);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Cancel'.toUpperCase()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _searchEnabled
|
||||
? () {
|
||||
widget.callback(_controller.text);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
: null,
|
||||
child: Text('Search'.toUpperCase()),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
// Copyright 2019 The Chromium 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 'dart:math';
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A widget that takes two children, lays them out along [axis], and allows
|
||||
/// the user to resize them.
|
||||
///
|
||||
/// The user can customize the amount of space allocated to each child by
|
||||
/// dragging a divider between them.
|
||||
///
|
||||
/// [initialFirstFraction] defines how much space to give the [firstChild]
|
||||
/// when first building this widget. [secondChild] will take the remaining
|
||||
/// space.
|
||||
///
|
||||
/// The user can drag the widget with key [dividerKey] to change
|
||||
/// the space allocated between [firstChild] and [secondChild].
|
||||
// TODO(djshuckerow): introduce support for a minimum fraction a child
|
||||
// is allowed.
|
||||
class Split extends StatefulWidget {
|
||||
/// Builds a split oriented along [axis].
|
||||
const Split({
|
||||
Key? key,
|
||||
required this.axis,
|
||||
required this.firstChild,
|
||||
required this.secondChild,
|
||||
double? initialFirstFraction,
|
||||
}) : initialFirstFraction = initialFirstFraction ?? 0.5,
|
||||
super(key: key);
|
||||
|
||||
/// The main axis the children will lay out on.
|
||||
///
|
||||
/// If [Axis.horizontal], the children will be placed in a [Row]
|
||||
/// and they will be horizontally resizable.
|
||||
///
|
||||
/// If [Axis.vertical], the children will be placed in a [Column]
|
||||
/// and they will be vertically resizable.
|
||||
///
|
||||
/// Cannot be null.
|
||||
final Axis axis;
|
||||
|
||||
/// The child that will be laid out first along [axis].
|
||||
final Widget firstChild;
|
||||
|
||||
/// The child that will be laid out last along [axis].
|
||||
final Widget secondChild;
|
||||
|
||||
/// The fraction of the layout to allocate to [firstChild].
|
||||
///
|
||||
/// [secondChild] will receive a fraction of `1 - initialFirstFraction`.
|
||||
final double initialFirstFraction;
|
||||
|
||||
/// The key passed to the divider between [firstChild] and [secondChild].
|
||||
///
|
||||
/// Visible to grab it in tests.
|
||||
@visibleForTesting
|
||||
Key get dividerKey => Key('$this dividerKey');
|
||||
|
||||
/// The size of the divider between [firstChild] and [secondChild] in
|
||||
/// logical pixels (dp, not px).
|
||||
static const double dividerMainAxisSize = 10;
|
||||
|
||||
static Axis axisFor(BuildContext context, double horizontalAspectRatio) {
|
||||
final screenSize = MediaQuery.of(context).size;
|
||||
final aspectRatio = screenSize.width / screenSize.height;
|
||||
if (aspectRatio >= horizontalAspectRatio) {
|
||||
return Axis.horizontal;
|
||||
}
|
||||
return Axis.vertical;
|
||||
}
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SplitState();
|
||||
}
|
||||
|
||||
class _SplitState extends State<Split> {
|
||||
late double firstFraction;
|
||||
|
||||
double get secondFraction => 1 - firstFraction;
|
||||
|
||||
bool get isHorizontal => widget.axis == Axis.horizontal;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
firstFraction = widget.initialFirstFraction;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(builder: _buildLayout);
|
||||
}
|
||||
|
||||
Widget _buildLayout(BuildContext context, BoxConstraints constraints) {
|
||||
final width = constraints.maxWidth;
|
||||
final height = constraints.maxHeight;
|
||||
final axisSize = isHorizontal ? width : height;
|
||||
final crossAxisSize = isHorizontal ? height : width;
|
||||
const halfDivider = Split.dividerMainAxisSize / 2.0;
|
||||
|
||||
// Determine what fraction to give each child, including enough space to
|
||||
// display the divider.
|
||||
var firstSize = axisSize * firstFraction;
|
||||
var secondSize = axisSize * secondFraction;
|
||||
|
||||
// Clamp the sizes to be sure there is enough space for the dividers.
|
||||
firstSize = firstSize.clamp(halfDivider, axisSize - halfDivider);
|
||||
secondSize = secondSize.clamp(halfDivider, axisSize - halfDivider);
|
||||
|
||||
// Remove space from each child to place the divider in the middle.
|
||||
firstSize = firstSize - halfDivider;
|
||||
secondSize = secondSize - halfDivider;
|
||||
|
||||
void updateSpacing(DragUpdateDetails dragDetails) {
|
||||
final delta = isHorizontal ? dragDetails.delta.dx : dragDetails.delta.dy;
|
||||
final fractionalDelta = delta / axisSize;
|
||||
setState(() {
|
||||
// Update the fraction of space consumed by the children,
|
||||
// being sure not to allocate any negative space.
|
||||
firstFraction += fractionalDelta;
|
||||
firstFraction = firstFraction.clamp(0.0, 1.0);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(https://github.com/flutter/flutter/issues/43747): use an icon.
|
||||
// The material icon for a drag handle is not currently available.
|
||||
// For now, draw an indicator that is 3 lines running in the direction
|
||||
// of the main axis, like a hamburger menu.
|
||||
// TODO(https://github.com/flutter/devtools/issues/1265): update mouse
|
||||
// to indicate that this is resizable.
|
||||
final dragIndicator = Flex(
|
||||
direction: isHorizontal ? Axis.vertical : Axis.horizontal,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (var i = 0; i < min(crossAxisSize / 6.0, 3).floor(); i++)
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: isHorizontal ? 2.0 : 0.0,
|
||||
horizontal: isHorizontal ? 0.0 : 2.0,
|
||||
),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).dividerColor,
|
||||
borderRadius: BorderRadius.circular(Split.dividerMainAxisSize),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: isHorizontal ? 2.0 : Split.dividerMainAxisSize - 2.0,
|
||||
width: isHorizontal ? Split.dividerMainAxisSize - 2.0 : 2.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final children = [
|
||||
SizedBox(
|
||||
width: isHorizontal ? firstSize : width,
|
||||
height: isHorizontal ? height : firstSize,
|
||||
child: widget.firstChild,
|
||||
),
|
||||
GestureDetector(
|
||||
key: widget.dividerKey,
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onHorizontalDragUpdate: isHorizontal ? updateSpacing : null,
|
||||
onVerticalDragUpdate: isHorizontal ? null : updateSpacing,
|
||||
// DartStartBehavior.down is needed to keep the mouse pointer stuck to
|
||||
// the drag bar. There still appears to be a few frame lag before the
|
||||
// drag action triggers which is't ideal but isn't a launch blocker.
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
child: SizedBox(
|
||||
width: isHorizontal ? Split.dividerMainAxisSize : width,
|
||||
height: isHorizontal ? height : Split.dividerMainAxisSize,
|
||||
child: Center(
|
||||
child: dragIndicator,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: isHorizontal ? secondSize : width,
|
||||
height: isHorizontal ? height : secondSize,
|
||||
child: widget.secondChild,
|
||||
),
|
||||
];
|
||||
return Flex(direction: widget.axis, children: children);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +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.
|
||||
|
||||
// TODO: Retrieve an API Access Key from https://unsplash.com/developers
|
||||
const String unsplashAccessKey = '';
|
||||
|
||||
// The application name for the above API Access Key.
|
||||
const unsplashAppName = '';
|
||||
@@ -1 +0,0 @@
|
||||
flutter/ephemeral
|
||||
@@ -1,116 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
set(BINARY_NAME "desktop_photo_search")
|
||||
set(APPLICATION_ID "com.example.desktop_photo_search")
|
||||
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Root filesystem for cross-building.
|
||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endif()
|
||||
|
||||
# Configure build options.
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||
endfunction()
|
||||
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
|
||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||
|
||||
# Application build
|
||||
add_executable(${BINARY_NAME}
|
||||
"main.cc"
|
||||
"my_application.cc"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
)
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
# Only the install-generated bundle's copy of the executable will launch
|
||||
# correctly, since the resources must in the right relative locations. To avoid
|
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||
# the default top-level location.
|
||||
set_target_properties(${BINARY_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||
)
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# By default, "installing" just makes a relocatable bundle in the build
|
||||
# directory.
|
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# Start with a clean build bundle directory every time.
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
@@ -1,87 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||
# which isn't available in 3.10.
|
||||
function(list_prepend LIST_NAME PREFIX)
|
||||
set(NEW_LIST "")
|
||||
foreach(element ${${LIST_NAME}})
|
||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||
endforeach(element)
|
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# === Flutter Library ===
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"fl_basic_message_channel.h"
|
||||
"fl_binary_codec.h"
|
||||
"fl_binary_messenger.h"
|
||||
"fl_dart_project.h"
|
||||
"fl_engine.h"
|
||||
"fl_json_message_codec.h"
|
||||
"fl_json_method_codec.h"
|
||||
"fl_message_codec.h"
|
||||
"fl_method_call.h"
|
||||
"fl_method_channel.h"
|
||||
"fl_method_codec.h"
|
||||
"fl_method_response.h"
|
||||
"fl_plugin_registrar.h"
|
||||
"fl_plugin_registry.h"
|
||||
"fl_standard_message_codec.h"
|
||||
"fl_standard_method_codec.h"
|
||||
"fl_string_codec.h"
|
||||
"fl_value.h"
|
||||
"fl_view.h"
|
||||
"flutter_linux.h"
|
||||
)
|
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||
target_link_libraries(flutter INTERFACE
|
||||
PkgConfig::GTK
|
||||
PkgConfig::GLIB
|
||||
PkgConfig::GIO
|
||||
)
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
)
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <menubar/menubar_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) menubar_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MenubarPlugin");
|
||||
menubar_plugin_register_with_registrar(menubar_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||
@@ -1,18 +0,0 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
menubar
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "my_application.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
g_autoptr(MyApplication) app = my_application_new();
|
||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
#include "my_application.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
struct _MyApplication {
|
||||
GtkApplication parent_instance;
|
||||
char** dart_entrypoint_arguments;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
|
||||
// Use a header bar when running in GNOME as this is the common style used
|
||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||
// desktop).
|
||||
// If running on X and not using GNOME then just use a traditional title bar
|
||||
// in case the window manager does more exotic layout, e.g. tiling.
|
||||
// If running on Wayland assume the header bar will work (may need changing
|
||||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
GdkScreen* screen = gtk_window_get_screen(window);
|
||||
if (GDK_IS_X11_SCREEN(screen)) {
|
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||
use_header_bar = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (use_header_bar) {
|
||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||
gtk_header_bar_set_title(header_bar, "Desktop Photo Search");
|
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||
} else {
|
||||
gtk_window_set_title(window, "Desktop Photo Search");
|
||||
}
|
||||
|
||||
gtk_window_set_default_size(window, 1280, 720);
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||
}
|
||||
|
||||
// Implements GApplication::local_command_line.
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
// Strip out the first argument as it is the binary name.
|
||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!g_application_register(application, nullptr, &error)) {
|
||||
g_warning("Failed to register: %s", error->message);
|
||||
*exit_status = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_application_activate(application);
|
||||
*exit_status = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Implements GObject::dispose.
|
||||
static void my_application_dispose(GObject* object) {
|
||||
MyApplication* self = MY_APPLICATION(object);
|
||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void my_application_class_init(MyApplicationClass* klass) {
|
||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||
}
|
||||
|
||||
static void my_application_init(MyApplication* self) {}
|
||||
|
||||
MyApplication* my_application_new() {
|
||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||
"application-id", APPLICATION_ID,
|
||||
"flags", G_APPLICATION_NON_UNIQUE,
|
||||
nullptr));
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||
#define FLUTTER_MY_APPLICATION_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
|
||||
GtkApplication)
|
||||
|
||||
/**
|
||||
* my_application_new:
|
||||
*
|
||||
* Creates a new Flutter-based application.
|
||||
*
|
||||
* Returns: a new #MyApplication.
|
||||
*/
|
||||
MyApplication* my_application_new();
|
||||
|
||||
#endif // FLUTTER_MY_APPLICATION_H_
|
||||
@@ -1,7 +0,0 @@
|
||||
# Flutter-related
|
||||
**/Flutter/ephemeral/
|
||||
**/Pods/
|
||||
|
||||
# Xcode-related
|
||||
**/dgph
|
||||
**/xcuserdata/
|
||||
@@ -1,2 +0,0 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
@@ -1,2 +0,0 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import file_selector_macos
|
||||
import menubar
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||
MenubarPlugin.register(with: registry.registrar(forPlugin: "MenubarPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
platform :osx, '10.11'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_macos_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_macos_build_settings(target)
|
||||
end
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
PODS:
|
||||
- file_selector_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- menubar (0.0.2):
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- menubar (from `Flutter/ephemeral/.symlinks/plugins/menubar/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_selector_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
menubar:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/menubar/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
file_selector_macos: ff6dc948d4ddd34e8602a1f60b7d0b4cc6051a47
|
||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||
menubar: 4e3d461d62d775540277ce6639acafe2a111a231
|
||||
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.11.2
|
||||
@@ -1,632 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
|
||||
buildPhases = (
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Flutter Assemble";
|
||||
productName = FLX;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
8ABDE709CC9129175CD43B5F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21AE7B3C5CDD0DA1EAFA8192 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
|
||||
remoteInfo = FLX;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Bundle Framework";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
046E9402D77CB52F3798A183 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
21AE7B3C5CDD0DA1EAFA8192 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* desktop_photo_search.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktop_photo_search.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
60162069BE152E865D1D4DAB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
DC7189FCCB4FDF54645192CA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8ABDE709CC9129175CD43B5F /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
33BA886A226E78AF003329D5 /* Configs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
|
||||
);
|
||||
path = Configs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10E42044A3C60003C045 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33FAB671232836740065AC1E /* Runner */,
|
||||
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||
33CC10EE2044A3C60003C045 /* Products */,
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||
E89324751EAA25FFD85ED79A /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* desktop_photo_search.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC11242044D66E0003C045 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */,
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */,
|
||||
33CC10F72044A3C60003C045 /* Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
path = ..;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CEB47122A05771004F2AC0 /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
|
||||
);
|
||||
path = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33FAB671232836740065AC1E /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||
33E51914231749380026EE4D /* Release.entitlements */,
|
||||
33CC11242044D66E0003C045 /* Resources */,
|
||||
33BA886A226E78AF003329D5 /* Configs */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21AE7B3C5CDD0DA1EAFA8192 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E89324751EAA25FFD85ED79A /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
60162069BE152E865D1D4DAB /* Pods-Runner.debug.xcconfig */,
|
||||
DC7189FCCB4FDF54645192CA /* Pods-Runner.release.xcconfig */,
|
||||
046E9402D77CB52F3798A183 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
33CC10EC2044A3C60003C045 /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
2986F46935953F8FA456F0C3 /* [CP] Check Pods Manifest.lock */,
|
||||
33CC10E92044A3C60003C045 /* Sources */,
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
9F18BB647558AC903DBF34ED /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* desktop_photo_search.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
33CC10E52044A3C60003C045 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0930;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
33CC111A2044C6BA0003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 33CC10E42044A3C60003C045;
|
||||
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
33CC10EC2044A3C60003C045 /* Runner */,
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
33CC10EB2044A3C60003C045 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
2986F46935953F8FA456F0C3 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||
};
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterInputs.xcfilelist,
|
||||
);
|
||||
inputPaths = (
|
||||
Flutter/ephemeral/tripwire,
|
||||
);
|
||||
outputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterOutputs.xcfilelist,
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||
};
|
||||
9F18BB647558AC903DBF34ED /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
33CC10E92044A3C60003C045 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
|
||||
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
33CC10F52044A3C60003C045 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
338D0CE9231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEA231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEB231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
33CC10F92044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FA2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC10FC2044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FD2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC111C2044C6BA0003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC111D2044C6BA0003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10F92044A3C60003C045 /* Debug */,
|
||||
33CC10FA2044A3C60003C045 /* Release */,
|
||||
338D0CE9231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10FC2044A3C60003C045 /* Debug */,
|
||||
33CC10FD2044A3C60003C045 /* Release */,
|
||||
338D0CEA231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC111C2044C6BA0003C045 /* Debug */,
|
||||
33CC111D2044C6BA0003C045 /* Release */,
|
||||
338D0CEB231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Photo Search.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Photo Search.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Photo Search.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Photo Search.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,13 +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 Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: FlutterAppDelegate {
|
||||
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_16.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_32.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_128.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_256.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_256.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_512.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_512.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "app_icon_1024.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,341 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Hiding the title bar technique from https://medium.com/flutter-community/transparent-title-bar-on-macos-with-flutter-7043d44f25dc -->
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19162" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19162"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Photo_Search" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
|
||||
<outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="APP_NAME" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About APP_NAME" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
<point key="canvasLocation" x="142" y="-258"/>
|
||||
</menu>
|
||||
<window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" titlebarAppearsTransparent="YES" titleVisibility="hidden" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Photo_Search" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="800" height="600"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1025"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<point key="canvasLocation" x="139" y="139"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -1,14 +0,0 @@
|
||||
// Application-level settings for the Runner target.
|
||||
//
|
||||
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
|
||||
// future. If not, the values below would default to using the project name when this becomes a
|
||||
// 'flutter create' template.
|
||||
|
||||
// The application's name. By default this is also the title of the Flutter window.
|
||||
PRODUCT_NAME = Photo Search
|
||||
|
||||
// The application's bundle identifier
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.desktopPhotoSearch
|
||||
|
||||
// The copyright displayed in application information
|
||||
PRODUCT_COPYRIGHT = Copyright © 2020 com.example. All rights reserved.
|
||||
@@ -1,2 +0,0 @@
|
||||
#include "../../Flutter/Flutter-Debug.xcconfig"
|
||||
#include "Warnings.xcconfig"
|
||||
@@ -1,2 +0,0 @@
|
||||
#include "../../Flutter/Flutter-Release.xcconfig"
|
||||
#include "Warnings.xcconfig"
|
||||
@@ -1,13 +0,0 @@
|
||||
WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES
|
||||
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
|
||||
CLANG_WARN_PRAGMA_PACK = YES
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES
|
||||
CLANG_WARN_COMMA = YES
|
||||
GCC_WARN_STRICT_SELECTOR_MATCH = YES
|
||||
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
|
||||
GCC_WARN_SHADOW = YES
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>$(PRODUCT_COPYRIGHT)</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,19 +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 Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
class MainFlutterWindow: NSWindow {
|
||||
override func awakeFromNib() {
|
||||
let flutterViewController = FlutterViewController.init()
|
||||
let windowFrame = self.frame
|
||||
self.contentViewController = flutterViewController
|
||||
self.setFrame(windowFrame, display: true)
|
||||
|
||||
RegisterGeneratedPlugins(registry: flutterViewController)
|
||||
|
||||
super.awakeFromNib()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,693 +0,0 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "31.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.0"
|
||||
ansicolor:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ansicolor
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.8"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
async:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
build:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.2.3"
|
||||
built_collection:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: built_collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.1.3"
|
||||
built_value_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: built_value_generator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.1.3"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.5"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
file_selector:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.2+1"
|
||||
file_selector_linux:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_selector_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.2+1"
|
||||
file_selector_macos:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_selector_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4+1"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
file_selector_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.1+2"
|
||||
file_selector_windows:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_selector_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.2+1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_simple_treeview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_simple_treeview
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
grinder:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: grinder
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.13.4"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
injector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: injector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.4.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
menubar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "plugins/menubar"
|
||||
ref: HEAD
|
||||
resolved-ref: c339fe7dd2e17a80f7bb839bfad89d21a6e084ba
|
||||
url: "https://github.com/google/flutter-desktop-embedding.git"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
msix:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: msix
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.4.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1+1"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_gen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.3"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
transparent_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: transparent_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.17"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.13"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.13"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
uuid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: uuid
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.3.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
dart: ">=2.14.0 <3.0.0"
|
||||
flutter: ">=2.5.0"
|
||||
@@ -1,57 +0,0 @@
|
||||
name: desktop_photo_search
|
||||
description: Search for Photos, using the Unsplash API.
|
||||
version: 1.0.0+1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
flutter: ^2.0.0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
built_collection: ^5.0.0
|
||||
built_value: ^8.0.3
|
||||
cupertino_icons: ^1.0.2
|
||||
file_selector: ^0.8.2
|
||||
file_selector_linux: ^0.0.1
|
||||
file_selector_macos: ^0.0.1
|
||||
file_selector_windows: ^0.0.1
|
||||
http: ^0.13.0
|
||||
logging: ^1.0.1
|
||||
flutter_simple_treeview: ^3.0.0-nullsafety.1
|
||||
menubar:
|
||||
git:
|
||||
url: https://github.com/google/flutter-desktop-embedding.git
|
||||
path: plugins/menubar
|
||||
meta: ^1.1.8
|
||||
provider: ^5.0.0
|
||||
transparent_image: ^2.0.0
|
||||
uuid: ^3.0.1
|
||||
url_launcher: ^6.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
async: ^2.4.0
|
||||
build: ^2.0.2
|
||||
build_runner: ^2.0.4
|
||||
built_value_generator: ^8.0.3
|
||||
grinder: ^0.9.0
|
||||
msix: ^2.1.2
|
||||
source_gen: ^1.0.1
|
||||
flutter_lints: ^1.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
msix_config:
|
||||
display_name: Flutter Desktop Photo Search
|
||||
publisher_display_name: flutter.dev
|
||||
publisher: CN=01A6D5C0-D51A-4EEE-8DD0-F134DDD378F7
|
||||
identity_name: 16354flutter.dev.FlutterDesktopPhotoSearch
|
||||
msix_version: 1.0.0.0
|
||||
icons_background_color: "#ffffff"
|
||||
architecture: x64
|
||||
# See https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations
|
||||
capabilities: "internetClient"
|
||||
@@ -1,536 +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:desktop_photo_search/src/unsplash/photo.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/search_photos_response.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/unsplash.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/user.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:http/testing.dart';
|
||||
|
||||
void main() {
|
||||
test('Photo.fromJson', () {
|
||||
const input = '''
|
||||
{
|
||||
"id": "Dwu85P9SOIk",
|
||||
"created_at": "2016-05-03T11:00:28-04:00",
|
||||
"updated_at": "2016-07-10T11:00:01-05:00",
|
||||
"width": 2448,
|
||||
"height": 3264,
|
||||
"color": "#6E633A",
|
||||
"downloads": 1345,
|
||||
"likes": 24,
|
||||
"liked_by_user": false,
|
||||
"description": "A man drinking a coffee.",
|
||||
"exif": {
|
||||
"make": "Canon",
|
||||
"model": "Canon EOS 40D",
|
||||
"exposure_time": "0.011111111111111112",
|
||||
"aperture": "4.970854",
|
||||
"focal_length": "37",
|
||||
"iso": 100
|
||||
},
|
||||
"location": {
|
||||
"city": "Montreal",
|
||||
"country": "Canada",
|
||||
"position": {
|
||||
"latitude": 45.4732984,
|
||||
"longitude": -73.6384879
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{ "title": "man" },
|
||||
{ "title": "drinking" },
|
||||
{ "title": "coffee" }
|
||||
],
|
||||
"current_user_collections": [
|
||||
{
|
||||
"id": 206,
|
||||
"title": "Makers: Cat and Ben",
|
||||
"published_at": "2016-01-12T18:16:09-05:00",
|
||||
"updated_at": "2016-07-10T11:00:01-05:00",
|
||||
"cover_photo": null,
|
||||
"user": null
|
||||
}
|
||||
],
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1417325384643-aac51acc9e5d",
|
||||
"full": "https://images.unsplash.com/photo-1417325384643-aac51acc9e5d?q=75&fm=jpg",
|
||||
"regular": "https://images.unsplash.com/photo-1417325384643-aac51acc9e5d?q=75&fm=jpg&w=1080&fit=max",
|
||||
"small": "https://images.unsplash.com/photo-1417325384643-aac51acc9e5d?q=75&fm=jpg&w=400&fit=max",
|
||||
"thumb": "https://images.unsplash.com/photo-1417325384643-aac51acc9e5d?q=75&fm=jpg&w=200&fit=max"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/Dwu85P9SOIk",
|
||||
"html": "https://unsplash.com/photos/Dwu85P9SOIk",
|
||||
"download": "https://unsplash.com/photos/Dwu85P9SOIk/download",
|
||||
"download_location": "https://api.unsplash.com/photos/Dwu85P9SOIk/download"
|
||||
},
|
||||
"user": {
|
||||
"id": "QPxL2MGqfrw",
|
||||
"updated_at": "2016-07-10T11:00:01-05:00",
|
||||
"username": "exampleuser",
|
||||
"name": "Joe Example",
|
||||
"portfolio_url": "https://example.com/",
|
||||
"bio": "Just an everyday Joe",
|
||||
"location": "Montreal",
|
||||
"total_likes": 5,
|
||||
"total_photos": 10,
|
||||
"total_collections": 13,
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/exampleuser",
|
||||
"html": "https://unsplash.com/exampleuser",
|
||||
"photos": "https://api.unsplash.com/users/exampleuser/photos",
|
||||
"likes": "https://api.unsplash.com/users/exampleuser/likes",
|
||||
"portfolio": "https://api.unsplash.com/users/exampleuser/portfolio"
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
final photo = Photo.fromJson(input)!;
|
||||
expect(photo.id, 'Dwu85P9SOIk');
|
||||
expect(photo.createdAt, '2016-05-03T11:00:28-04:00');
|
||||
expect(photo.updatedAt, '2016-07-10T11:00:01-05:00');
|
||||
expect(photo.width, 2448);
|
||||
expect(photo.height, 3264);
|
||||
expect(photo.color, '#6E633A');
|
||||
expect(photo.downloads, 1345);
|
||||
expect(photo.likedByUser, false);
|
||||
expect(photo.exif!.make, 'Canon');
|
||||
expect(photo.exif!.iso, 100);
|
||||
expect(photo.location!.city, 'Montreal');
|
||||
expect(photo.location!.country, 'Canada');
|
||||
expect(photo.location!.position!.latitude, 45.4732984);
|
||||
expect(photo.location!.position!.longitude, -73.6384879);
|
||||
});
|
||||
|
||||
test('User.fromJson', () {
|
||||
const input = '''
|
||||
{
|
||||
"id": "pXhwzz1JtQU",
|
||||
"updated_at": "2016-07-10T11:00:01-05:00",
|
||||
"username": "jimmyexample",
|
||||
"name": "James Example",
|
||||
"first_name": "James",
|
||||
"last_name": "Example",
|
||||
"instagram_username": "instantgrammer",
|
||||
"twitter_username": "jimmy",
|
||||
"portfolio_url": null,
|
||||
"bio": "The user's bio",
|
||||
"location": "Montreal, Qc",
|
||||
"total_likes": 20,
|
||||
"total_photos": 10,
|
||||
"total_collections": 5,
|
||||
"followed_by_user": false,
|
||||
"followers_count": 300,
|
||||
"following_count": 25,
|
||||
"downloads": 225974,
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/face-springmorning.jpg?q=80&fm=jpg&crop=faces&fit=crop&h=32&w=32",
|
||||
"medium": "https://images.unsplash.com/face-springmorning.jpg?q=80&fm=jpg&crop=faces&fit=crop&h=64&w=64",
|
||||
"large": "https://images.unsplash.com/face-springmorning.jpg?q=80&fm=jpg&crop=faces&fit=crop&h=128&w=128"
|
||||
},
|
||||
"badge": {
|
||||
"title": "Book contributor",
|
||||
"primary": true,
|
||||
"slug": "book-contributor",
|
||||
"link": "https://book.unsplash.com"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/jimmyexample",
|
||||
"html": "https://unsplash.com/jimmyexample",
|
||||
"photos": "https://api.unsplash.com/users/jimmyexample/photos",
|
||||
"likes": "https://api.unsplash.com/users/jimmyexample/likes",
|
||||
"portfolio": "https://api.unsplash.com/users/jimmyexample/portfolio"
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
final user = User.fromJson(input)!;
|
||||
expect(user.id, 'pXhwzz1JtQU');
|
||||
});
|
||||
|
||||
test('SearchPhotosResponse.fromJson', () {
|
||||
const input = '''
|
||||
{
|
||||
"total": 133,
|
||||
"total_pages": 7,
|
||||
"results": [
|
||||
{
|
||||
"id": "eOLpJytrbsQ",
|
||||
"created_at": "2014-11-18T14:35:36-05:00",
|
||||
"width": 4000,
|
||||
"height": 3000,
|
||||
"color": "#A7A2A1",
|
||||
"likes": 286,
|
||||
"liked_by_user": false,
|
||||
"description": "A man drinking a coffee.",
|
||||
"user": {
|
||||
"id": "Ul0QVz12Goo",
|
||||
"username": "ugmonk",
|
||||
"name": "Jeff Sheldon",
|
||||
"first_name": "Jeff",
|
||||
"last_name": "Sheldon",
|
||||
"instagram_username": "instantgrammer",
|
||||
"twitter_username": "ugmonk",
|
||||
"portfolio_url": "http://ugmonk.com/",
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
|
||||
"medium": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
|
||||
"large": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/ugmonk",
|
||||
"html": "http://unsplash.com/@ugmonk",
|
||||
"photos": "https://api.unsplash.com/users/ugmonk/photos",
|
||||
"likes": "https://api.unsplash.com/users/ugmonk/likes"
|
||||
}
|
||||
},
|
||||
"current_user_collections": [],
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
|
||||
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
|
||||
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/eOLpJytrbsQ",
|
||||
"html": "http://unsplash.com/photos/eOLpJytrbsQ",
|
||||
"download": "http://unsplash.com/photos/eOLpJytrbsQ/download"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
final response = SearchPhotosResponse.fromJson(input)!;
|
||||
expect(response.total, 133);
|
||||
expect(response.totalPages, 7);
|
||||
expect(response.results[0].id, 'eOLpJytrbsQ');
|
||||
expect(response.results[0].user!.id, 'Ul0QVz12Goo');
|
||||
});
|
||||
|
||||
group('Unsplash API client', () {
|
||||
test('handles success', () async {
|
||||
const searchPhotosResponseBody = '''
|
||||
{
|
||||
"total": 133,
|
||||
"total_pages": 7,
|
||||
"results": [
|
||||
{
|
||||
"id": "eOLpJytrbsQ",
|
||||
"created_at": "2014-11-18T14:35:36-05:00",
|
||||
"width": 4000,
|
||||
"height": 3000,
|
||||
"color": "#A7A2A1",
|
||||
"likes": 286,
|
||||
"liked_by_user": false,
|
||||
"description": "A man drinking a coffee.",
|
||||
"user": {
|
||||
"id": "Ul0QVz12Goo",
|
||||
"username": "ugmonk",
|
||||
"name": "Jeff Sheldon",
|
||||
"first_name": "Jeff",
|
||||
"last_name": "Sheldon",
|
||||
"instagram_username": "instantgrammer",
|
||||
"twitter_username": "ugmonk",
|
||||
"portfolio_url": "http://ugmonk.com/",
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
|
||||
"medium": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
|
||||
"large": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/ugmonk",
|
||||
"html": "http://unsplash.com/@ugmonk",
|
||||
"photos": "https://api.unsplash.com/users/ugmonk/photos",
|
||||
"likes": "https://api.unsplash.com/users/ugmonk/likes"
|
||||
}
|
||||
},
|
||||
"current_user_collections": [],
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
|
||||
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
|
||||
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/eOLpJytrbsQ",
|
||||
"html": "http://unsplash.com/photos/eOLpJytrbsQ",
|
||||
"download": "http://unsplash.com/photos/eOLpJytrbsQ/download"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
final httpClient = MockClient((req) async {
|
||||
return Response(
|
||||
searchPhotosResponseBody,
|
||||
200,
|
||||
request: req,
|
||||
headers: {'content-type': 'application/json'},
|
||||
);
|
||||
});
|
||||
|
||||
final unsplashClient = Unsplash(
|
||||
accessKey: 'not-an-access-key',
|
||||
httpClient: httpClient,
|
||||
);
|
||||
|
||||
final response = (await unsplashClient.searchPhotos(query: 'red'))!;
|
||||
|
||||
expect(response.total, 133);
|
||||
expect(response.totalPages, 7);
|
||||
expect(response.results[0].id, 'eOLpJytrbsQ');
|
||||
expect(response.results[0].user!.id, 'Ul0QVz12Goo');
|
||||
});
|
||||
|
||||
test('handles failure', () async {
|
||||
const apiError =
|
||||
'{"errors":["OAuth error: The access token is invalid"]}';
|
||||
|
||||
final httpClient = MockClient((req) async {
|
||||
return Response(
|
||||
apiError,
|
||||
401,
|
||||
request: req,
|
||||
headers: {'content-type': 'application/json'},
|
||||
);
|
||||
});
|
||||
|
||||
final unsplashClient = Unsplash(
|
||||
accessKey: 'not-an-access-key',
|
||||
httpClient: httpClient,
|
||||
);
|
||||
|
||||
try {
|
||||
await unsplashClient.searchPhotos(query: 'red');
|
||||
fail('UnsplashException should have been thrown');
|
||||
} on UnsplashException catch (e) {
|
||||
expect(e.toString(),
|
||||
'UnsplashException: OAuth error: The access token is invalid');
|
||||
}
|
||||
});
|
||||
|
||||
test('handles broken JSON', () async {
|
||||
const apiError = '{"tot'; // truncated JSON.
|
||||
|
||||
final httpClient = MockClient((req) async {
|
||||
return Response(
|
||||
apiError,
|
||||
401,
|
||||
request: req,
|
||||
headers: {'content-type': 'application/json'},
|
||||
);
|
||||
});
|
||||
|
||||
final unsplashClient = Unsplash(
|
||||
accessKey: 'not-an-access-key',
|
||||
httpClient: httpClient,
|
||||
);
|
||||
|
||||
try {
|
||||
await unsplashClient.searchPhotos(query: 'red');
|
||||
fail('UnsplashException should have been thrown');
|
||||
} on UnsplashException catch (e) {
|
||||
expect(e.toString(), 'UnsplashException: Invalid JSON received');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('handles utf8 content in JSON', () async {
|
||||
const searchPhotosResponseBody = '''
|
||||
{
|
||||
"total": 22395,
|
||||
"total_pages": 2240,
|
||||
"results": [
|
||||
{
|
||||
"id": "E4u_Zo9PET8",
|
||||
"created_at": "2019-12-29T13:45:28-05:00",
|
||||
"updated_at": "2020-11-05T17:12:18-05:00",
|
||||
"promoted_at": null,
|
||||
"width": 2598,
|
||||
"height": 4618,
|
||||
"color": "#A53E40",
|
||||
"blur_hash": "LlO{8lL#XSbu*Jtla0jZOrb^ozjF",
|
||||
"description": null,
|
||||
"alt_description": "red apparel",
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1577645113639-32537a4a938b?ixlib=rb-1.2.1\u0026ixid=eyJhcHBfaWQiOjM5NTU5fQ",
|
||||
"full": "https://images.unsplash.com/photo-1577645113639-32537a4a938b?ixlib=rb-1.2.1\u0026q=85\u0026fm=jpg\u0026crop=entropy\u0026cs=srgb\u0026ixid=eyJhcHBfaWQiOjM5NTU5fQ",
|
||||
"regular": "https://images.unsplash.com/photo-1577645113639-32537a4a938b?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjM5NTU5fQ",
|
||||
"small": "https://images.unsplash.com/photo-1577645113639-32537a4a938b?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=400\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjM5NTU5fQ",
|
||||
"thumb": "https://images.unsplash.com/photo-1577645113639-32537a4a938b?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=200\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjM5NTU5fQ"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/E4u_Zo9PET8",
|
||||
"html": "https://unsplash.com/photos/E4u_Zo9PET8",
|
||||
"download": "https://unsplash.com/photos/E4u_Zo9PET8/download",
|
||||
"download_location": "https://api.unsplash.com/photos/E4u_Zo9PET8/download"
|
||||
},
|
||||
"categories": [],
|
||||
"likes": 132,
|
||||
"liked_by_user": false,
|
||||
"current_user_collections": [],
|
||||
"sponsorship": null,
|
||||
"user": {
|
||||
"id": "_2nQcPrbyuE",
|
||||
"updated_at": "2020-11-06T01:37:51-05:00",
|
||||
"username": "svalenas",
|
||||
"name": "Sergiu Vălenaș",
|
||||
"first_name": "Sergiu",
|
||||
"last_name": "Vălenaș",
|
||||
"twitter_username": null,
|
||||
"portfolio_url": null,
|
||||
"bio": "Gifted psychologist and enthusiast photographer",
|
||||
"location": "Cluj-Napoca, Romania",
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/svalenas",
|
||||
"html": "https://unsplash.com/@svalenas",
|
||||
"photos": "https://api.unsplash.com/users/svalenas/photos",
|
||||
"likes": "https://api.unsplash.com/users/svalenas/likes",
|
||||
"portfolio": "https://api.unsplash.com/users/svalenas/portfolio",
|
||||
"following": "https://api.unsplash.com/users/svalenas/following",
|
||||
"followers": "https://api.unsplash.com/users/svalenas/followers"
|
||||
},
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/profile-1597067601066-d43176d68553image?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=32\u0026w=32",
|
||||
"medium": "https://images.unsplash.com/profile-1597067601066-d43176d68553image?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=64\u0026w=64",
|
||||
"large": "https://images.unsplash.com/profile-1597067601066-d43176d68553image?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=128\u0026w=128"
|
||||
},
|
||||
"instagram_username": "svalenas",
|
||||
"total_collections": 0,
|
||||
"total_likes": 413,
|
||||
"total_photos": 129,
|
||||
"accepted_tos": true
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"type": "landing_page",
|
||||
"title": "red",
|
||||
"source": {
|
||||
"ancestry": {
|
||||
"type": {
|
||||
"slug": "wallpapers",
|
||||
"pretty_slug": "HD Wallpapers"
|
||||
},
|
||||
"category": {
|
||||
"slug": "colors",
|
||||
"pretty_slug": "Color"
|
||||
},
|
||||
"subcategory": {
|
||||
"slug": "red",
|
||||
"pretty_slug": "Red"
|
||||
}
|
||||
},
|
||||
"title": "HD Red Wallpapers",
|
||||
"subtitle": "Download Free Red Wallpapers",
|
||||
"description": "Choose from a curated selection of red wallpapers for your mobile and desktop screens. Always free on Unsplash.",
|
||||
"meta_title": "Red Wallpapers: Free HD Download [500+ HQ] | Unsplash",
|
||||
"meta_description": "Choose from hundreds of free red wallpapers. Download HD wallpapers for free on Unsplash.",
|
||||
"cover_photo": {
|
||||
"id": "HyBXy5PHQR8",
|
||||
"created_at": "2018-02-17T13:44:58-05:00",
|
||||
"updated_at": "2020-10-21T01:07:42-04:00",
|
||||
"promoted_at": null,
|
||||
"width": 3024,
|
||||
"height": 4032,
|
||||
"color": "#C51918",
|
||||
"blur_hash": "L9Bmx_o1o1Jl|cwxWpWpN]\$5N]sU",
|
||||
"description": null,
|
||||
"alt_description": "red textile",
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1518893063132-36e46dbe2428?ixlib=rb-1.2.1",
|
||||
"full": "https://images.unsplash.com/photo-1518893063132-36e46dbe2428?ixlib=rb-1.2.1\u0026q=85\u0026fm=jpg\u0026crop=entropy\u0026cs=srgb",
|
||||
"regular": "https://images.unsplash.com/photo-1518893063132-36e46dbe2428?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max",
|
||||
"small": "https://images.unsplash.com/photo-1518893063132-36e46dbe2428?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=400\u0026fit=max",
|
||||
"thumb": "https://images.unsplash.com/photo-1518893063132-36e46dbe2428?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=200\u0026fit=max"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/HyBXy5PHQR8",
|
||||
"html": "https://unsplash.com/photos/HyBXy5PHQR8",
|
||||
"download": "https://unsplash.com/photos/HyBXy5PHQR8/download",
|
||||
"download_location": "https://api.unsplash.com/photos/HyBXy5PHQR8/download"
|
||||
},
|
||||
"categories": [],
|
||||
"likes": 1243,
|
||||
"liked_by_user": false,
|
||||
"current_user_collections": [],
|
||||
"sponsorship": null,
|
||||
"user": {
|
||||
"id": "6nkkrwW9M-s",
|
||||
"updated_at": "2020-10-22T20:44:54-04:00",
|
||||
"username": "montylov",
|
||||
"name": "MontyLov",
|
||||
"first_name": "MontyLov",
|
||||
"last_name": null,
|
||||
"twitter_username": "MontyLov",
|
||||
"portfolio_url": "http://montylov.com",
|
||||
"bio": "Stay humble and innovate.",
|
||||
"location": null,
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/montylov",
|
||||
"html": "https://unsplash.com/@montylov",
|
||||
"photos": "https://api.unsplash.com/users/montylov/photos",
|
||||
"likes": "https://api.unsplash.com/users/montylov/likes",
|
||||
"portfolio": "https://api.unsplash.com/users/montylov/portfolio",
|
||||
"following": "https://api.unsplash.com/users/montylov/following",
|
||||
"followers": "https://api.unsplash.com/users/montylov/followers"
|
||||
},
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/profile-1588478301600-b5e5203a574aimage?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=32\u0026w=32",
|
||||
"medium": "https://images.unsplash.com/profile-1588478301600-b5e5203a574aimage?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=64\u0026w=64",
|
||||
"large": "https://images.unsplash.com/profile-1588478301600-b5e5203a574aimage?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=128\u0026w=128"
|
||||
},
|
||||
"instagram_username": "montylov",
|
||||
"total_collections": 1,
|
||||
"total_likes": 0,
|
||||
"total_photos": 79,
|
||||
"accepted_tos": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"title": "rug"
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"title": "plant"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
final httpClient = MockClient((req) async {
|
||||
return Response(
|
||||
searchPhotosResponseBody,
|
||||
200,
|
||||
request: req,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
|
||||
final unsplashClient = Unsplash(
|
||||
accessKey: 'not-an-access-key',
|
||||
httpClient: httpClient,
|
||||
);
|
||||
|
||||
final response = (await unsplashClient.searchPhotos(query: 'red'))!;
|
||||
|
||||
expect(response.total, 22395);
|
||||
expect(response.totalPages, 2240);
|
||||
expect(response.results[0].id, 'E4u_Zo9PET8');
|
||||
expect(response.results[0].user!.id, '_2nQcPrbyuE');
|
||||
expect(response.results[0].user!.name, 'Sergiu Vălenaș');
|
||||
});
|
||||
}
|
||||
@@ -1,134 +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 'dart:typed_data';
|
||||
|
||||
import 'package:desktop_photo_search/src/model/photo_search_model.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/photo.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/search_photos_response.dart';
|
||||
import 'package:desktop_photo_search/src/unsplash/unsplash.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FakeUnsplash implements Unsplash {
|
||||
static const searchPhotosResponse = '''
|
||||
{
|
||||
"total": 133,
|
||||
"total_pages": 7,
|
||||
"results": [
|
||||
{
|
||||
"id": "eOLpJytrbsQ",
|
||||
"created_at": "2014-11-18T14:35:36-05:00",
|
||||
"width": 4000,
|
||||
"height": 3000,
|
||||
"color": "#A7A2A1",
|
||||
"likes": 286,
|
||||
"liked_by_user": false,
|
||||
"description": "A man drinking a coffee.",
|
||||
"user": {
|
||||
"id": "Ul0QVz12Goo",
|
||||
"username": "ugmonk",
|
||||
"name": "Jeff Sheldon",
|
||||
"first_name": "Jeff",
|
||||
"last_name": "Sheldon",
|
||||
"instagram_username": "instantgrammer",
|
||||
"twitter_username": "ugmonk",
|
||||
"portfolio_url": "http://ugmonk.com/",
|
||||
"profile_image": {
|
||||
"small": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
|
||||
"medium": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
|
||||
"large": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/users/ugmonk",
|
||||
"html": "http://unsplash.com/@ugmonk",
|
||||
"photos": "https://api.unsplash.com/users/ugmonk/photos",
|
||||
"likes": "https://api.unsplash.com/users/ugmonk/likes"
|
||||
}
|
||||
},
|
||||
"current_user_collections": [],
|
||||
"urls": {
|
||||
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
|
||||
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
|
||||
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
|
||||
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
|
||||
},
|
||||
"links": {
|
||||
"self": "https://api.unsplash.com/photos/eOLpJytrbsQ",
|
||||
"html": "http://unsplash.com/photos/eOLpJytrbsQ",
|
||||
"download": "http://unsplash.com/photos/eOLpJytrbsQ/download"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
@override
|
||||
Future<SearchPhotosResponse?> searchPhotos(
|
||||
{String? query,
|
||||
num page = 1,
|
||||
num perPage = 10,
|
||||
List<num> collections = const [],
|
||||
SearchPhotosOrientation? orientation}) async {
|
||||
return SearchPhotosResponse.fromJson(searchPhotosResponse);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> download(Photo photo) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
const fabKey = Key('fab');
|
||||
|
||||
class PhotoSearchModelTester extends StatelessWidget {
|
||||
const PhotoSearchModelTester({required this.query, Key? key})
|
||||
: super(key: key);
|
||||
final String query;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: TextButton(
|
||||
key: fabKey,
|
||||
onPressed: () async {
|
||||
await Provider.of<PhotoSearchModel>(
|
||||
context,
|
||||
listen: false,
|
||||
).addSearch(query);
|
||||
},
|
||||
child: const Text('Search for a Photo'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('search_list', () {
|
||||
testWidgets('starts empty', (tester) async {
|
||||
final unsplashSearches = PhotoSearchModel(FakeUnsplash());
|
||||
final testWidget = ChangeNotifierProvider<PhotoSearchModel>(
|
||||
create: (context) => unsplashSearches,
|
||||
child: const PhotoSearchModelTester(query: 'clouds'),
|
||||
);
|
||||
await tester.pumpWidget(testWidget);
|
||||
expect(unsplashSearches.entries.length, 0);
|
||||
});
|
||||
|
||||
testWidgets('addSearch adds searches', (tester) async {
|
||||
final unsplashSearches = PhotoSearchModel(FakeUnsplash());
|
||||
final testWidget = ChangeNotifierProvider<PhotoSearchModel>(
|
||||
create: (context) => unsplashSearches,
|
||||
child: const PhotoSearchModelTester(query: 'clouds'),
|
||||
);
|
||||
await tester.pumpWidget(testWidget);
|
||||
await tester.tap(find.byKey(fabKey));
|
||||
await tester.tap(find.byKey(fabKey));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(unsplashSearches.entries.length, 2);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,72 +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 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:async/async.dart' show StreamGroup;
|
||||
import 'package:grinder/grinder.dart';
|
||||
|
||||
void main(List<String> args) => grind(args);
|
||||
|
||||
@DefaultTask()
|
||||
@Depends(pubGet, generateJsonBindings, analyzeSource, test)
|
||||
void build() {}
|
||||
|
||||
@Task()
|
||||
Future<void> pubGet() async => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['pub', 'get'],
|
||||
),
|
||||
);
|
||||
|
||||
@Task()
|
||||
Future<void> generateJsonBindings() async => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['pub', 'run', 'build_runner', 'build', '--delete-conflicting-outputs'],
|
||||
),
|
||||
);
|
||||
|
||||
@Task()
|
||||
Future<void> watch() async => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['pub', 'run', 'build_runner', 'watch'],
|
||||
),
|
||||
);
|
||||
|
||||
@Task()
|
||||
Future<void> analyzeSource() async => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['analyze'],
|
||||
),
|
||||
);
|
||||
|
||||
@Task()
|
||||
Future<void> test() async => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['test'],
|
||||
),
|
||||
);
|
||||
|
||||
@Task()
|
||||
Future<void> clean() => _logProcessOutput(
|
||||
Process.start(
|
||||
'flutter',
|
||||
['clean'],
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> _logProcessOutput(Future<Process> proc) async {
|
||||
final process = await proc;
|
||||
final output = StreamGroup.merge([process.stdout, process.stderr]);
|
||||
await for (final message in output) {
|
||||
log(utf8.decode(message));
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
flutter/ephemeral/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
@@ -1,95 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(desktop_photo_search LANGUAGES CXX)
|
||||
|
||||
set(BINARY_NAME "desktop_photo_search")
|
||||
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Configure build options.
|
||||
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(IS_MULTICONFIG)
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
||||
CACHE STRING "" FORCE)
|
||||
else()
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
# Use Unicode for all projects.
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
||||
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
||||
target_compile_options(${TARGET} PRIVATE /EHsc)
|
||||
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
||||
endfunction()
|
||||
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# Application build
|
||||
add_subdirectory("runner")
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# Support files are copied into place next to the executable, so that it can
|
||||
# run in place. This is done instead of making a separate bundle (as on Linux)
|
||||
# so that building and running from within Visual Studio will work.
|
||||
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
||||
# Make the "install" step default, as it's required to run.
|
||||
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
CONFIGURATIONS Profile;Release
|
||||
COMPONENT Runtime)
|
||||
@@ -1,103 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
|
||||
|
||||
# === Flutter Library ===
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"flutter_export.h"
|
||||
"flutter_windows.h"
|
||||
"flutter_messenger.h"
|
||||
"flutter_plugin_registrar.h"
|
||||
"flutter_texture_registrar.h"
|
||||
)
|
||||
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Wrapper ===
|
||||
list(APPEND CPP_WRAPPER_SOURCES_CORE
|
||||
"core_implementations.cc"
|
||||
"standard_codec.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
|
||||
"plugin_registrar.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_APP
|
||||
"flutter_engine.cc"
|
||||
"flutter_view_controller.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
|
||||
|
||||
# Wrapper sources needed for a plugin.
|
||||
add_library(flutter_wrapper_plugin STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_plugin)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_plugin PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_plugin flutter_assemble)
|
||||
|
||||
# Wrapper sources needed for the runner.
|
||||
add_library(flutter_wrapper_app STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_app)
|
||||
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_app PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_app flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
|
||||
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
${PHONY_OUTPUT}
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
|
||||
windows-x64 $<CONFIG>
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_windows/file_selector_plugin.h>
|
||||
#include <menubar/menubar_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FileSelectorPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FileSelectorPlugin"));
|
||||
MenubarPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("MenubarPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter/plugin_registry.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||
@@ -1,18 +0,0 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_windows
|
||||
menubar
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
@@ -1,17 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
add_executable(${BINARY_NAME} WIN32
|
||||
"flutter_window.cpp"
|
||||
"main.cpp"
|
||||
"utils.cpp"
|
||||
"win32_window.cpp"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
"Runner.rc"
|
||||
"runner.exe.manifest"
|
||||
)
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
@@ -1,121 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
#ifdef FLUTTER_BUILD_NUMBER
|
||||
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
|
||||
#else
|
||||
#define VERSION_AS_NUMBER 1,0,0
|
||||
#endif
|
||||
|
||||
#ifdef FLUTTER_BUILD_NAME
|
||||
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
|
||||
#else
|
||||
#define VERSION_AS_STRING "1.0.0"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_AS_NUMBER
|
||||
PRODUCTVERSION VERSION_AS_NUMBER
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "FileDescription", "A new Flutter project." "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "desktop_photo_search" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2020 com.example. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "desktop_photo_search.exe" "\0"
|
||||
VALUE "ProductName", "desktop_photo_search" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "flutter_window.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||
: project_(project) {}
|
||||
|
||||
FlutterWindow::~FlutterWindow() {}
|
||||
|
||||
bool FlutterWindow::OnCreate() {
|
||||
if (!Win32Window::OnCreate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
// The size here must match the window dimensions to avoid unnecessary surface
|
||||
// creation / destruction in the startup path.
|
||||
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
|
||||
frame.right - frame.left, frame.bottom - frame.top, project_);
|
||||
// Ensure that basic setup of the controller was successful.
|
||||
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
|
||||
return false;
|
||||
}
|
||||
RegisterPlugins(flutter_controller_->engine());
|
||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlutterWindow::OnDestroy() {
|
||||
if (flutter_controller_) {
|
||||
flutter_controller_ = nullptr;
|
||||
}
|
||||
|
||||
Win32Window::OnDestroy();
|
||||
}
|
||||
|
||||
LRESULT
|
||||
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
// Give Flutter, including plugins, an opportunity to handle window messages.
|
||||
if (flutter_controller_) {
|
||||
std::optional<LRESULT> result =
|
||||
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
||||
lparam);
|
||||
if (result) {
|
||||
return *result;
|
||||
}
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_FONTCHANGE:
|
||||
flutter_controller_->engine()->ReloadSystemFonts();
|
||||
break;
|
||||
}
|
||||
|
||||
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||||
#define RUNNER_FLUTTER_WINDOW_H_
|
||||
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "win32_window.h"
|
||||
|
||||
// A window that does nothing but host a Flutter view.
|
||||
class FlutterWindow : public Win32Window {
|
||||
public:
|
||||
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||
explicit FlutterWindow(const flutter::DartProject& project);
|
||||
virtual ~FlutterWindow();
|
||||
|
||||
protected:
|
||||
// Win32Window:
|
||||
bool OnCreate() override;
|
||||
void OnDestroy() override;
|
||||
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept override;
|
||||
|
||||
private:
|
||||
// The project to run.
|
||||
flutter::DartProject project_;
|
||||
|
||||
// The Flutter instance hosted by this window.
|
||||
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
||||
};
|
||||
|
||||
#endif // RUNNER_FLUTTER_WINDOW_H_
|
||||
@@ -1,43 +0,0 @@
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "flutter_window.h"
|
||||
#include "utils.h"
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
CreateAndAttachConsole();
|
||||
}
|
||||
|
||||
// Initialize COM, so that it is available for use in the library and/or
|
||||
// plugins.
|
||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
flutter::DartProject project(L"data");
|
||||
|
||||
std::vector<std::string> command_line_arguments =
|
||||
GetCommandLineArguments();
|
||||
|
||||
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||
|
||||
FlutterWindow window(project);
|
||||
Win32Window::Point origin(10, 10);
|
||||
Win32Window::Size size(1280, 720);
|
||||
if (!window.CreateAndShow(L"Desktop Photo Search", origin, size)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
window.SetQuitOnClose(true);
|
||||
|
||||
::MSG msg;
|
||||
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
::CoUninitialize();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Runner.rc
|
||||
//
|
||||
#define IDI_APP_ICON 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 33 KiB |
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
@@ -1,64 +0,0 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <flutter_windows.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void CreateAndAttachConsole() {
|
||||
if (::AllocConsole()) {
|
||||
FILE *unused;
|
||||
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
|
||||
_dup2(_fileno(stdout), 1);
|
||||
}
|
||||
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
|
||||
_dup2(_fileno(stdout), 2);
|
||||
}
|
||||
std::ios::sync_with_stdio();
|
||||
FlutterDesktopResyncOutputStreams();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> GetCommandLineArguments() {
|
||||
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
|
||||
int argc;
|
||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
if (argv == nullptr) {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::vector<std::string> command_line_arguments;
|
||||
|
||||
// Skip the first argument as it's the binary name.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
||||
}
|
||||
|
||||
::LocalFree(argv);
|
||||
|
||||
return command_line_arguments;
|
||||
}
|
||||
|
||||
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
||||
if (utf16_string == nullptr) {
|
||||
return std::string();
|
||||
}
|
||||
int target_length = ::WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||
-1, nullptr, 0, nullptr, nullptr);
|
||||
if (target_length == 0) {
|
||||
return std::string();
|
||||
}
|
||||
std::string utf8_string;
|
||||
utf8_string.resize(target_length);
|
||||
int converted_length = ::WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||
-1, utf8_string.data(),
|
||||
target_length, nullptr, nullptr);
|
||||
if (converted_length == 0) {
|
||||
return std::string();
|
||||
}
|
||||
return utf8_string;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef RUNNER_UTILS_H_
|
||||
#define RUNNER_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Creates a console for the process, and redirects stdout and stderr to
|
||||
// it for both the runner and the Flutter library.
|
||||
void CreateAndAttachConsole();
|
||||
|
||||
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
|
||||
// encoded in UTF-8. Returns an empty std::string on failure.
|
||||
std::string Utf8FromUtf16(const wchar_t* utf16_string);
|
||||
|
||||
// Gets the command line arguments passed in as a std::vector<std::string>,
|
||||
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
||||
std::vector<std::string> GetCommandLineArguments();
|
||||
|
||||
#endif // RUNNER_UTILS_H_
|
||||
@@ -1,245 +0,0 @@
|
||||
#include "win32_window.h"
|
||||
|
||||
#include <flutter_windows.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
||||
|
||||
// The number of Win32Window objects that currently exist.
|
||||
static int g_active_window_count = 0;
|
||||
|
||||
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
|
||||
|
||||
// Scale helper to convert logical scaler values to physical using passed in
|
||||
// scale factor
|
||||
int Scale(int source, double scale_factor) {
|
||||
return static_cast<int>(source * scale_factor);
|
||||
}
|
||||
|
||||
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
|
||||
// This API is only needed for PerMonitor V1 awareness mode.
|
||||
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
||||
HMODULE user32_module = LoadLibraryA("User32.dll");
|
||||
if (!user32_module) {
|
||||
return;
|
||||
}
|
||||
auto enable_non_client_dpi_scaling =
|
||||
reinterpret_cast<EnableNonClientDpiScaling*>(
|
||||
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
||||
if (enable_non_client_dpi_scaling != nullptr) {
|
||||
enable_non_client_dpi_scaling(hwnd);
|
||||
FreeLibrary(user32_module);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Manages the Win32Window's window class registration.
|
||||
class WindowClassRegistrar {
|
||||
public:
|
||||
~WindowClassRegistrar() = default;
|
||||
|
||||
// Returns the singleton registar instance.
|
||||
static WindowClassRegistrar* GetInstance() {
|
||||
if (!instance_) {
|
||||
instance_ = new WindowClassRegistrar();
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
// Returns the name of the window class, registering the class if it hasn't
|
||||
// previously been registered.
|
||||
const wchar_t* GetWindowClass();
|
||||
|
||||
// Unregisters the window class. Should only be called if there are no
|
||||
// instances of the window.
|
||||
void UnregisterWindowClass();
|
||||
|
||||
private:
|
||||
WindowClassRegistrar() = default;
|
||||
|
||||
static WindowClassRegistrar* instance_;
|
||||
|
||||
bool class_registered_ = false;
|
||||
};
|
||||
|
||||
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
||||
|
||||
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
||||
if (!class_registered_) {
|
||||
WNDCLASS window_class{};
|
||||
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
window_class.lpszClassName = kWindowClassName;
|
||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
window_class.cbClsExtra = 0;
|
||||
window_class.cbWndExtra = 0;
|
||||
window_class.hInstance = GetModuleHandle(nullptr);
|
||||
window_class.hIcon =
|
||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
||||
window_class.hbrBackground = 0;
|
||||
window_class.lpszMenuName = nullptr;
|
||||
window_class.lpfnWndProc = Win32Window::WndProc;
|
||||
RegisterClass(&window_class);
|
||||
class_registered_ = true;
|
||||
}
|
||||
return kWindowClassName;
|
||||
}
|
||||
|
||||
void WindowClassRegistrar::UnregisterWindowClass() {
|
||||
UnregisterClass(kWindowClassName, nullptr);
|
||||
class_registered_ = false;
|
||||
}
|
||||
|
||||
Win32Window::Win32Window() {
|
||||
++g_active_window_count;
|
||||
}
|
||||
|
||||
Win32Window::~Win32Window() {
|
||||
--g_active_window_count;
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool Win32Window::CreateAndShow(const std::wstring& title,
|
||||
const Point& origin,
|
||||
const Size& size) {
|
||||
Destroy();
|
||||
|
||||
const wchar_t* window_class =
|
||||
WindowClassRegistrar::GetInstance()->GetWindowClass();
|
||||
|
||||
const POINT target_point = {static_cast<LONG>(origin.x),
|
||||
static_cast<LONG>(origin.y)};
|
||||
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
|
||||
UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
|
||||
double scale_factor = dpi / 96.0;
|
||||
|
||||
HWND window = CreateWindow(
|
||||
window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
|
||||
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
||||
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return OnCreate();
|
||||
}
|
||||
|
||||
// static
|
||||
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
if (message == WM_NCCREATE) {
|
||||
auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
||||
SetWindowLongPtr(window, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
||||
|
||||
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
||||
EnableFullDpiSupportIfAvailable(window);
|
||||
that->window_handle_ = window;
|
||||
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
||||
return that->MessageHandler(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
return DefWindowProc(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT
|
||||
Win32Window::MessageHandler(HWND hwnd,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
switch (message) {
|
||||
case WM_DESTROY:
|
||||
window_handle_ = nullptr;
|
||||
Destroy();
|
||||
if (quit_on_close_) {
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_DPICHANGED: {
|
||||
auto newRectSize = reinterpret_cast<RECT*>(lparam);
|
||||
LONG newWidth = newRectSize->right - newRectSize->left;
|
||||
LONG newHeight = newRectSize->bottom - newRectSize->top;
|
||||
|
||||
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
|
||||
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
case WM_SIZE: {
|
||||
RECT rect = GetClientArea();
|
||||
if (child_content_ != nullptr) {
|
||||
// Size and position the child window.
|
||||
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top, TRUE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_ACTIVATE:
|
||||
if (child_content_ != nullptr) {
|
||||
SetFocus(child_content_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(window_handle_, message, wparam, lparam);
|
||||
}
|
||||
|
||||
void Win32Window::Destroy() {
|
||||
OnDestroy();
|
||||
|
||||
if (window_handle_) {
|
||||
DestroyWindow(window_handle_);
|
||||
window_handle_ = nullptr;
|
||||
}
|
||||
if (g_active_window_count == 0) {
|
||||
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
|
||||
}
|
||||
}
|
||||
|
||||
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
|
||||
return reinterpret_cast<Win32Window*>(
|
||||
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
void Win32Window::SetChildContent(HWND content) {
|
||||
child_content_ = content;
|
||||
SetParent(content, window_handle_);
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
||||
frame.bottom - frame.top, true);
|
||||
|
||||
SetFocus(child_content_);
|
||||
}
|
||||
|
||||
RECT Win32Window::GetClientArea() {
|
||||
RECT frame;
|
||||
GetClientRect(window_handle_, &frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
HWND Win32Window::GetHandle() {
|
||||
return window_handle_;
|
||||
}
|
||||
|
||||
void Win32Window::SetQuitOnClose(bool quit_on_close) {
|
||||
quit_on_close_ = quit_on_close;
|
||||
}
|
||||
|
||||
bool Win32Window::OnCreate() {
|
||||
// No-op; provided for subclasses.
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32Window::OnDestroy() {
|
||||
// No-op; provided for subclasses.
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
#ifndef RUNNER_WIN32_WINDOW_H_
|
||||
#define RUNNER_WIN32_WINDOW_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
||||
// inherited from by classes that wish to specialize with custom
|
||||
// rendering and input handling
|
||||
class Win32Window {
|
||||
public:
|
||||
struct Point {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
||||
};
|
||||
|
||||
struct Size {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
Size(unsigned int width, unsigned int height)
|
||||
: width(width), height(height) {}
|
||||
};
|
||||
|
||||
Win32Window();
|
||||
virtual ~Win32Window();
|
||||
|
||||
// Creates and shows a win32 window with |title| and position and size using
|
||||
// |origin| and |size|. New windows are created on the default monitor. Window
|
||||
// sizes are specified to the OS in physical pixels, hence to ensure a
|
||||
// consistent size to will treat the width height passed in to this function
|
||||
// as logical pixels and scale to appropriate for the default monitor. Returns
|
||||
// true if the window was created successfully.
|
||||
bool CreateAndShow(const std::wstring& title,
|
||||
const Point& origin,
|
||||
const Size& size);
|
||||
|
||||
// Release OS resources associated with window.
|
||||
void Destroy();
|
||||
|
||||
// Inserts |content| into the window tree.
|
||||
void SetChildContent(HWND content);
|
||||
|
||||
// Returns the backing Window handle to enable clients to set icon and other
|
||||
// window properties. Returns nullptr if the window has been destroyed.
|
||||
HWND GetHandle();
|
||||
|
||||
// If true, closing this window will quit the application.
|
||||
void SetQuitOnClose(bool quit_on_close);
|
||||
|
||||
// Return a RECT representing the bounds of the current client area.
|
||||
RECT GetClientArea();
|
||||
|
||||
protected:
|
||||
// Processes and route salient window messages for mouse handling,
|
||||
// size change and DPI. Delegates handling of these to member overloads that
|
||||
// inheriting classes can handle.
|
||||
virtual LRESULT MessageHandler(HWND window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
|
||||
// Called when CreateAndShow is called, allowing subclass window-related
|
||||
// setup. Subclasses should return false if setup fails.
|
||||
virtual bool OnCreate();
|
||||
|
||||
// Called when Destroy is called.
|
||||
virtual void OnDestroy();
|
||||
|
||||
private:
|
||||
friend class WindowClassRegistrar;
|
||||
|
||||
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
||||
// is passed when the non-client area is being created and enables automatic
|
||||
// non-client DPI scaling so that the non-client area automatically
|
||||
// responsponds to changes in DPI. All other messages are handled by
|
||||
// MessageHandler.
|
||||
static LRESULT CALLBACK WndProc(HWND const window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
|
||||
// Retrieves a class instance pointer for |window|
|
||||
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
||||
|
||||
bool quit_on_close_ = false;
|
||||
|
||||
// window handle for top level window.
|
||||
HWND window_handle_ = nullptr;
|
||||
|
||||
// window handle for hosted content.
|
||||
HWND child_content_ = nullptr;
|
||||
};
|
||||
|
||||
#endif // RUNNER_WIN32_WINDOW_H_
|
||||