mirror of
https://github.com/flutter/samples.git
synced 2026-04-05 11:11:23 +00:00
Migrate desktop_photo_search to top level (#1002)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
// 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);
|
||||
}
|
||||
36
desktop_photo_search/material/lib/src/model/search.dart
Normal file
36
desktop_photo_search/material/lib/src/model/search.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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;
|
||||
}
|
||||
166
desktop_photo_search/material/lib/src/model/search.g.dart
Normal file
166
desktop_photo_search/material/lib/src/model/search.g.dart
Normal file
@@ -0,0 +1,166 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
27
desktop_photo_search/material/lib/src/serializers.dart
Normal file
27
desktop_photo_search/material/lib/src/serializers.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
// 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();
|
||||
44
desktop_photo_search/material/lib/src/serializers.g.dart
Normal file
44
desktop_photo_search/material/lib/src/serializers.g.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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;
|
||||
}
|
||||
146
desktop_photo_search/material/lib/src/unsplash/api_error.g.dart
Normal file
146
desktop_photo_search/material/lib/src/unsplash/api_error.g.dart
Normal file
@@ -0,0 +1,146 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
47
desktop_photo_search/material/lib/src/unsplash/exif.dart
Normal file
47
desktop_photo_search/material/lib/src/unsplash/exif.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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;
|
||||
}
|
||||
251
desktop_photo_search/material/lib/src/unsplash/exif.g.dart
Normal file
251
desktop_photo_search/material/lib/src/unsplash/exif.g.dart
Normal file
@@ -0,0 +1,251 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
41
desktop_photo_search/material/lib/src/unsplash/links.dart
Normal file
41
desktop_photo_search/material/lib/src/unsplash/links.dart
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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;
|
||||
}
|
||||
200
desktop_photo_search/material/lib/src/unsplash/links.g.dart
Normal file
200
desktop_photo_search/material/lib/src/unsplash/links.g.dart
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
39
desktop_photo_search/material/lib/src/unsplash/location.dart
Normal file
39
desktop_photo_search/material/lib/src/unsplash/location.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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;
|
||||
}
|
||||
187
desktop_photo_search/material/lib/src/unsplash/location.g.dart
Normal file
187
desktop_photo_search/material/lib/src/unsplash/location.g.dart
Normal file
@@ -0,0 +1,187 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
88
desktop_photo_search/material/lib/src/unsplash/photo.dart
Normal file
88
desktop_photo_search/material/lib/src/unsplash/photo.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
// 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;
|
||||
}
|
||||
553
desktop_photo_search/material/lib/src/unsplash/photo.g.dart
Normal file
553
desktop_photo_search/material/lib/src/unsplash/photo.g.dart
Normal file
@@ -0,0 +1,553 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
35
desktop_photo_search/material/lib/src/unsplash/position.dart
Normal file
35
desktop_photo_search/material/lib/src/unsplash/position.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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;
|
||||
}
|
||||
152
desktop_photo_search/material/lib/src/unsplash/position.g.dart
Normal file
152
desktop_photo_search/material/lib/src/unsplash/position.g.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
32
desktop_photo_search/material/lib/src/unsplash/tags.dart
Normal file
32
desktop_photo_search/material/lib/src/unsplash/tags.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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;
|
||||
}
|
||||
131
desktop_photo_search/material/lib/src/unsplash/tags.g.dart
Normal file
131
desktop_photo_search/material/lib/src/unsplash/tags.g.dart
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
118
desktop_photo_search/material/lib/src/unsplash/unsplash.dart
Normal file
118
desktop_photo_search/material/lib/src/unsplash/unsplash.dart
Normal file
@@ -0,0 +1,118 @@
|
||||
// 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';
|
||||
}
|
||||
}
|
||||
44
desktop_photo_search/material/lib/src/unsplash/urls.dart
Normal file
44
desktop_photo_search/material/lib/src/unsplash/urls.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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;
|
||||
}
|
||||
217
desktop_photo_search/material/lib/src/unsplash/urls.g.dart
Normal file
217
desktop_photo_search/material/lib/src/unsplash/urls.g.dart
Normal file
@@ -0,0 +1,217 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
63
desktop_photo_search/material/lib/src/unsplash/user.dart
Normal file
63
desktop_photo_search/material/lib/src/unsplash/user.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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;
|
||||
}
|
||||
377
desktop_photo_search/material/lib/src/unsplash/user.g.dart
Normal file
377
desktop_photo_search/material/lib/src/unsplash/user.g.dart
Normal file
@@ -0,0 +1,377 @@
|
||||
// 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,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new
|
||||
113
desktop_photo_search/material/lib/src/widgets/photo_details.dart
Normal file
113
desktop_photo_search/material/lib/src/widgets/photo_details.dart
Normal file
@@ -0,0 +1,113 @@
|
||||
// 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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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: const Text('CANCEL'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _searchEnabled
|
||||
? () {
|
||||
widget.callback(_controller.text);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
: null,
|
||||
child: const Text('SEARCH'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Terms & Conditions'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
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: const Text('CLOSE'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
190
desktop_photo_search/material/lib/src/widgets/split.dart
Normal file
190
desktop_photo_search/material/lib/src/widgets/split.dart
Normal file
@@ -0,0 +1,190 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright 2022 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';
|
||||
|
||||
import '../../unsplash_access_key.dart';
|
||||
|
||||
final _unsplashHomepage =
|
||||
'https://unsplash.com/?utm_source=${Uri.encodeFull(unsplashAppName)}&utm_medium=referral';
|
||||
final _unsplashPrivacyPolicy =
|
||||
'https://unsplash.com/privacy?utm_source=${Uri.encodeFull(unsplashAppName)}&utm_medium=referral';
|
||||
|
||||
class UnsplashNotice extends StatefulWidget {
|
||||
const UnsplashNotice({Key? key, required this.child}) : super(key: key);
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<UnsplashNotice> createState() => _UnsplashNoticeState();
|
||||
}
|
||||
|
||||
class _UnsplashNoticeState extends State<UnsplashNotice> {
|
||||
bool noticeAccepted = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
|
||||
showDialog<void>(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return _UnsplashDialog(accepted: () {
|
||||
setState(() {
|
||||
noticeAccepted = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child;
|
||||
}
|
||||
}
|
||||
|
||||
class _UnsplashDialog extends StatelessWidget {
|
||||
const _UnsplashDialog({Key? key, required this.accepted}) : super(key: key);
|
||||
final Function accepted;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Unsplash Notice'),
|
||||
content: RichText(
|
||||
text: TextSpan(
|
||||
text: 'This is a sample desktop application provided by Google'
|
||||
' that enables you to search ',
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Unsplash',
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
if (!await launch(_unsplashHomepage)) {
|
||||
throw 'Could not launch $_unsplashHomepage';
|
||||
}
|
||||
},
|
||||
style: const TextStyle(color: Colors.blue),
|
||||
),
|
||||
const TextSpan(
|
||||
text: ' for photographs that interest you. When you search'
|
||||
' for and interact with photos, Unsplash will collect'
|
||||
' information about you and your use of the Unsplash'
|
||||
' services. Learn more about ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'how Unsplash collects and uses data',
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
if (!await launch(_unsplashPrivacyPolicy)) {
|
||||
throw 'Could not launch $_unsplashPrivacyPolicy';
|
||||
}
|
||||
},
|
||||
style: const TextStyle(color: Colors.blue),
|
||||
),
|
||||
const TextSpan(
|
||||
text: '.',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
]),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('GOT IT'),
|
||||
onPressed: () {
|
||||
accepted();
|
||||
Navigator.pop(context);
|
||||
})
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2022 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:file_selector/file_selector.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_simple_treeview/flutter_simple_treeview.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../model/photo_search_model.dart';
|
||||
import '../unsplash/photo.dart';
|
||||
import '../widgets/photo_details.dart';
|
||||
import '../widgets/split.dart';
|
||||
|
||||
class UnsplashSearchContent extends StatefulWidget {
|
||||
const UnsplashSearchContent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<UnsplashSearchContent> createState() => _UnsplashSearchContentState();
|
||||
}
|
||||
|
||||
class _UnsplashSearchContentState extends State<UnsplashSearchContent> {
|
||||
final _treeViewScrollController = ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final photoSearchModel = Provider.of<PhotoSearchModel>(context);
|
||||
|
||||
return Split(
|
||||
axis: Axis.horizontal,
|
||||
initialFirstFraction: 0.4,
|
||||
firstChild: Scrollbar(
|
||||
controller: _treeViewScrollController,
|
||||
child: SingleChildScrollView(
|
||||
controller: _treeViewScrollController,
|
||||
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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
child: Text(labelForPhoto(photo)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user