mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
construct appflowy home screen
This commit is contained in:
parent
222f6c7ba7
commit
02f0eef08b
@ -66,6 +66,18 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_editor/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_editor/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_editor/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/flowy_editor/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/macos/Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/example/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
@ -219,6 +219,13 @@
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="expandable">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/expandable-4.1.4/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="fake_async">
|
||||
<value>
|
||||
<list>
|
||||
@ -238,7 +245,6 @@
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.2/lib" />
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.1/lib" />
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
@ -424,6 +430,13 @@
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="lint">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/lint-1.5.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="lints">
|
||||
<value>
|
||||
<list>
|
||||
@ -625,6 +638,13 @@
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="sized_context">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/sized_context-0.2.1+1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="sky_engine">
|
||||
<value>
|
||||
<list>
|
||||
@ -681,6 +701,13 @@
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="styled_widget">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/styled_widget-0.3.1+2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="sync_http">
|
||||
<value>
|
||||
<list>
|
||||
@ -739,6 +766,13 @@
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="universal_platform">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/universal_platform-0.1.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher">
|
||||
<value>
|
||||
<list>
|
||||
@ -801,7 +835,7 @@
|
||||
<entry key="vm_service">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-6.2.0/lib" />
|
||||
<option value="$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-7.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
@ -903,11 +937,11 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/dart_style-2.0.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/dartz-0.10.0-nullsafety.2/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/equatable-2.0.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/expandable-4.1.4/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/ffi-1.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/ffi-1.1.2/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/file-6.1.2/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/fixnum-1.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/flutter_bloc-7.0.1/lib" />
|
||||
@ -934,6 +968,7 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/isolates-3.0.3+8/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/json_annotation-4.0.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/lint-1.5.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/lints-1.0.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/logger-1.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/logging-1.0.1/lib" />
|
||||
@ -966,6 +1001,7 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/shelf-1.1.4/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-1.0.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/sized_context-0.2.1+1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_gen-1.0.2/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
|
||||
@ -973,6 +1009,7 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/stream_transform-2.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/string_validator-0.3.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/styled_widget-0.3.1+2/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.3.0/lib" />
|
||||
@ -983,6 +1020,7 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/timing-1.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/tuple-2.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/universal_platform-0.1.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.3/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.9/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-2.0.0/lib" />
|
||||
@ -994,7 +1032,7 @@
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-2.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/uuid-3.0.4/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-6.2.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-7.1.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/watcher-1.0.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.2.0/lib" />
|
||||
<root url="file://$PROJECT_DIR$/../../flutter/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-2.1.0/lib" />
|
||||
|
@ -0,0 +1,28 @@
|
||||
import 'package:app_flowy/home/domain/edit_context.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
part 'edit_pannel_event.dart';
|
||||
part 'edit_pannel_state.dart';
|
||||
part 'edit_pannel_bloc.freezed.dart';
|
||||
|
||||
class EditPannelBloc extends Bloc<EditPannelEvent, EditPannelState> {
|
||||
EditPannelBloc() : super(EditPannelState.initial());
|
||||
|
||||
@override
|
||||
Stream<EditPannelState> mapEventToState(
|
||||
EditPannelEvent event,
|
||||
) async* {
|
||||
yield* event.map(
|
||||
startEdit: (e) async* {
|
||||
yield state.copyWith(isEditing: true, editContext: some(e.context));
|
||||
},
|
||||
endEdit: (value) async* {
|
||||
yield state.copyWith(isEditing: false, editContext: none());
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,492 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
|
||||
|
||||
part of 'edit_pannel_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
class _$EditPannelEventTearOff {
|
||||
const _$EditPannelEventTearOff();
|
||||
|
||||
_StartEdit startEdit(EditPannelContext context) {
|
||||
return _StartEdit(
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
_EndEdit endEdit(EditPannelContext context) {
|
||||
return _EndEdit(
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $EditPannelEvent = _$EditPannelEventTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$EditPannelEvent {
|
||||
EditPannelContext get context => throw _privateConstructorUsedError;
|
||||
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(EditPannelContext context) startEdit,
|
||||
required TResult Function(EditPannelContext context) endEdit,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(EditPannelContext context)? startEdit,
|
||||
TResult Function(EditPannelContext context)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_StartEdit value) startEdit,
|
||||
required TResult Function(_EndEdit value) endEdit,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_StartEdit value)? startEdit,
|
||||
TResult Function(_EndEdit value)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$EditPannelEventCopyWith<EditPannelEvent> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $EditPannelEventCopyWith<$Res> {
|
||||
factory $EditPannelEventCopyWith(
|
||||
EditPannelEvent value, $Res Function(EditPannelEvent) then) =
|
||||
_$EditPannelEventCopyWithImpl<$Res>;
|
||||
$Res call({EditPannelContext context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$EditPannelEventCopyWithImpl<$Res>
|
||||
implements $EditPannelEventCopyWith<$Res> {
|
||||
_$EditPannelEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
final EditPannelEvent _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(EditPannelEvent) _then;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? context = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
context: context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as EditPannelContext,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$StartEditCopyWith<$Res>
|
||||
implements $EditPannelEventCopyWith<$Res> {
|
||||
factory _$StartEditCopyWith(
|
||||
_StartEdit value, $Res Function(_StartEdit) then) =
|
||||
__$StartEditCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({EditPannelContext context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$StartEditCopyWithImpl<$Res> extends _$EditPannelEventCopyWithImpl<$Res>
|
||||
implements _$StartEditCopyWith<$Res> {
|
||||
__$StartEditCopyWithImpl(_StartEdit _value, $Res Function(_StartEdit) _then)
|
||||
: super(_value, (v) => _then(v as _StartEdit));
|
||||
|
||||
@override
|
||||
_StartEdit get _value => super._value as _StartEdit;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? context = freezed,
|
||||
}) {
|
||||
return _then(_StartEdit(
|
||||
context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as EditPannelContext,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_StartEdit implements _StartEdit {
|
||||
const _$_StartEdit(this.context);
|
||||
|
||||
@override
|
||||
final EditPannelContext context;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EditPannelEvent.startEdit(context: $context)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _StartEdit &&
|
||||
(identical(other.context, context) ||
|
||||
const DeepCollectionEquality().equals(other.context, context)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(context);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$StartEditCopyWith<_StartEdit> get copyWith =>
|
||||
__$StartEditCopyWithImpl<_StartEdit>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(EditPannelContext context) startEdit,
|
||||
required TResult Function(EditPannelContext context) endEdit,
|
||||
}) {
|
||||
return startEdit(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(EditPannelContext context)? startEdit,
|
||||
TResult Function(EditPannelContext context)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (startEdit != null) {
|
||||
return startEdit(context);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_StartEdit value) startEdit,
|
||||
required TResult Function(_EndEdit value) endEdit,
|
||||
}) {
|
||||
return startEdit(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_StartEdit value)? startEdit,
|
||||
TResult Function(_EndEdit value)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (startEdit != null) {
|
||||
return startEdit(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _StartEdit implements EditPannelEvent {
|
||||
const factory _StartEdit(EditPannelContext context) = _$_StartEdit;
|
||||
|
||||
@override
|
||||
EditPannelContext get context => throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$StartEditCopyWith<_StartEdit> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$EndEditCopyWith<$Res>
|
||||
implements $EditPannelEventCopyWith<$Res> {
|
||||
factory _$EndEditCopyWith(_EndEdit value, $Res Function(_EndEdit) then) =
|
||||
__$EndEditCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({EditPannelContext context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$EndEditCopyWithImpl<$Res> extends _$EditPannelEventCopyWithImpl<$Res>
|
||||
implements _$EndEditCopyWith<$Res> {
|
||||
__$EndEditCopyWithImpl(_EndEdit _value, $Res Function(_EndEdit) _then)
|
||||
: super(_value, (v) => _then(v as _EndEdit));
|
||||
|
||||
@override
|
||||
_EndEdit get _value => super._value as _EndEdit;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? context = freezed,
|
||||
}) {
|
||||
return _then(_EndEdit(
|
||||
context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as EditPannelContext,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_EndEdit implements _EndEdit {
|
||||
const _$_EndEdit(this.context);
|
||||
|
||||
@override
|
||||
final EditPannelContext context;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EditPannelEvent.endEdit(context: $context)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _EndEdit &&
|
||||
(identical(other.context, context) ||
|
||||
const DeepCollectionEquality().equals(other.context, context)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(context);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$EndEditCopyWith<_EndEdit> get copyWith =>
|
||||
__$EndEditCopyWithImpl<_EndEdit>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(EditPannelContext context) startEdit,
|
||||
required TResult Function(EditPannelContext context) endEdit,
|
||||
}) {
|
||||
return endEdit(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(EditPannelContext context)? startEdit,
|
||||
TResult Function(EditPannelContext context)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (endEdit != null) {
|
||||
return endEdit(context);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_StartEdit value) startEdit,
|
||||
required TResult Function(_EndEdit value) endEdit,
|
||||
}) {
|
||||
return endEdit(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_StartEdit value)? startEdit,
|
||||
TResult Function(_EndEdit value)? endEdit,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (endEdit != null) {
|
||||
return endEdit(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _EndEdit implements EditPannelEvent {
|
||||
const factory _EndEdit(EditPannelContext context) = _$_EndEdit;
|
||||
|
||||
@override
|
||||
EditPannelContext get context => throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$EndEditCopyWith<_EndEdit> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$EditPannelStateTearOff {
|
||||
const _$EditPannelStateTearOff();
|
||||
|
||||
_EditPannelState call(
|
||||
{required bool isEditing,
|
||||
required Option<EditPannelContext> editContext}) {
|
||||
return _EditPannelState(
|
||||
isEditing: isEditing,
|
||||
editContext: editContext,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $EditPannelState = _$EditPannelStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$EditPannelState {
|
||||
bool get isEditing => throw _privateConstructorUsedError;
|
||||
Option<EditPannelContext> get editContext =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$EditPannelStateCopyWith<EditPannelState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $EditPannelStateCopyWith<$Res> {
|
||||
factory $EditPannelStateCopyWith(
|
||||
EditPannelState value, $Res Function(EditPannelState) then) =
|
||||
_$EditPannelStateCopyWithImpl<$Res>;
|
||||
$Res call({bool isEditing, Option<EditPannelContext> editContext});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$EditPannelStateCopyWithImpl<$Res>
|
||||
implements $EditPannelStateCopyWith<$Res> {
|
||||
_$EditPannelStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
final EditPannelState _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(EditPannelState) _then;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? isEditing = freezed,
|
||||
Object? editContext = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isEditing: isEditing == freezed
|
||||
? _value.isEditing
|
||||
: isEditing // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
editContext: editContext == freezed
|
||||
? _value.editContext
|
||||
: editContext // ignore: cast_nullable_to_non_nullable
|
||||
as Option<EditPannelContext>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$EditPannelStateCopyWith<$Res>
|
||||
implements $EditPannelStateCopyWith<$Res> {
|
||||
factory _$EditPannelStateCopyWith(
|
||||
_EditPannelState value, $Res Function(_EditPannelState) then) =
|
||||
__$EditPannelStateCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({bool isEditing, Option<EditPannelContext> editContext});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$EditPannelStateCopyWithImpl<$Res>
|
||||
extends _$EditPannelStateCopyWithImpl<$Res>
|
||||
implements _$EditPannelStateCopyWith<$Res> {
|
||||
__$EditPannelStateCopyWithImpl(
|
||||
_EditPannelState _value, $Res Function(_EditPannelState) _then)
|
||||
: super(_value, (v) => _then(v as _EditPannelState));
|
||||
|
||||
@override
|
||||
_EditPannelState get _value => super._value as _EditPannelState;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? isEditing = freezed,
|
||||
Object? editContext = freezed,
|
||||
}) {
|
||||
return _then(_EditPannelState(
|
||||
isEditing: isEditing == freezed
|
||||
? _value.isEditing
|
||||
: isEditing // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
editContext: editContext == freezed
|
||||
? _value.editContext
|
||||
: editContext // ignore: cast_nullable_to_non_nullable
|
||||
as Option<EditPannelContext>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_EditPannelState implements _EditPannelState {
|
||||
const _$_EditPannelState(
|
||||
{required this.isEditing, required this.editContext});
|
||||
|
||||
@override
|
||||
final bool isEditing;
|
||||
@override
|
||||
final Option<EditPannelContext> editContext;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EditPannelState(isEditing: $isEditing, editContext: $editContext)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _EditPannelState &&
|
||||
(identical(other.isEditing, isEditing) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.isEditing, isEditing)) &&
|
||||
(identical(other.editContext, editContext) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.editContext, editContext)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^
|
||||
const DeepCollectionEquality().hash(isEditing) ^
|
||||
const DeepCollectionEquality().hash(editContext);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$EditPannelStateCopyWith<_EditPannelState> get copyWith =>
|
||||
__$EditPannelStateCopyWithImpl<_EditPannelState>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _EditPannelState implements EditPannelState {
|
||||
const factory _EditPannelState(
|
||||
{required bool isEditing,
|
||||
required Option<EditPannelContext> editContext}) = _$_EditPannelState;
|
||||
|
||||
@override
|
||||
bool get isEditing => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<EditPannelContext> get editContext =>
|
||||
throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$EditPannelStateCopyWith<_EditPannelState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
part of 'edit_pannel_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class EditPannelEvent with _$EditPannelEvent {
|
||||
const factory EditPannelEvent.startEdit(EditPannelContext context) =
|
||||
_StartEdit;
|
||||
|
||||
const factory EditPannelEvent.endEdit(EditPannelContext context) = _EndEdit;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
part of 'edit_pannel_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class EditPannelState implements _$EditPannelState {
|
||||
const factory EditPannelState({
|
||||
required bool isEditing,
|
||||
required Option<EditPannelContext> editContext,
|
||||
}) = _EditPannelState;
|
||||
|
||||
factory EditPannelState.initial() => EditPannelState(
|
||||
isEditing: false,
|
||||
editContext: none(),
|
||||
);
|
||||
}
|
44
app_flowy/lib/home/application/menu/menu_bloc.dart
Normal file
44
app_flowy/lib/home/application/menu/menu_bloc.dart
Normal file
@ -0,0 +1,44 @@
|
||||
import 'dart:async';
|
||||
import 'package:app_flowy/home/domain/page_context.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
part 'menu_event.dart';
|
||||
part 'menu_state.dart';
|
||||
part 'menu_bloc.freezed.dart';
|
||||
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
MenuBloc() : super(MenuState.initial());
|
||||
|
||||
@override
|
||||
Stream<MenuState> mapEventToState(
|
||||
MenuEvent event,
|
||||
) async* {
|
||||
yield* event.map(
|
||||
collapse: (e) async* {
|
||||
final isCollapse = state.isCollapse;
|
||||
yield state.copyWith(isCollapse: !isCollapse);
|
||||
},
|
||||
openPage: (e) async* {
|
||||
yield* _performActionOnOpenPage(e);
|
||||
},
|
||||
createApp: (e) async* {
|
||||
yield* _performActionOnCreateApp(e);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Stream<MenuState> _performActionOnOpenPage(_OpenPage e) async* {
|
||||
yield state.copyWith(pageContext: some(e.context));
|
||||
}
|
||||
|
||||
Stream<MenuState> _performActionOnCreateApp(_CreateApp e) async* {
|
||||
yield state;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
return super.close();
|
||||
}
|
||||
}
|
525
app_flowy/lib/home/application/menu/menu_bloc.freezed.dart
Normal file
525
app_flowy/lib/home/application/menu/menu_bloc.freezed.dart
Normal file
@ -0,0 +1,525 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
|
||||
|
||||
part of 'menu_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuEventTearOff {
|
||||
const _$MenuEventTearOff();
|
||||
|
||||
Collapse collapse() {
|
||||
return const Collapse();
|
||||
}
|
||||
|
||||
_OpenPage openPage(PageContext context) {
|
||||
return _OpenPage(
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
_CreateApp createApp() {
|
||||
return const _CreateApp();
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $MenuEvent = _$MenuEventTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$MenuEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(PageContext context) openPage,
|
||||
required TResult Function() createApp,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? collapse,
|
||||
TResult Function(PageContext context)? openPage,
|
||||
TResult Function()? createApp,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Collapse value) collapse,
|
||||
required TResult Function(_OpenPage value) openPage,
|
||||
required TResult Function(_CreateApp value) createApp,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Collapse value)? collapse,
|
||||
TResult Function(_OpenPage value)? openPage,
|
||||
TResult Function(_CreateApp value)? createApp,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $MenuEventCopyWith<$Res> {
|
||||
factory $MenuEventCopyWith(MenuEvent value, $Res Function(MenuEvent) then) =
|
||||
_$MenuEventCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuEventCopyWithImpl<$Res> implements $MenuEventCopyWith<$Res> {
|
||||
_$MenuEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
final MenuEvent _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(MenuEvent) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $CollapseCopyWith<$Res> {
|
||||
factory $CollapseCopyWith(Collapse value, $Res Function(Collapse) then) =
|
||||
_$CollapseCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$CollapseCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
|
||||
implements $CollapseCopyWith<$Res> {
|
||||
_$CollapseCopyWithImpl(Collapse _value, $Res Function(Collapse) _then)
|
||||
: super(_value, (v) => _then(v as Collapse));
|
||||
|
||||
@override
|
||||
Collapse get _value => super._value as Collapse;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$Collapse implements Collapse {
|
||||
const _$Collapse();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuEvent.collapse()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is Collapse);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(PageContext context) openPage,
|
||||
required TResult Function() createApp,
|
||||
}) {
|
||||
return collapse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? collapse,
|
||||
TResult Function(PageContext context)? openPage,
|
||||
TResult Function()? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (collapse != null) {
|
||||
return collapse();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Collapse value) collapse,
|
||||
required TResult Function(_OpenPage value) openPage,
|
||||
required TResult Function(_CreateApp value) createApp,
|
||||
}) {
|
||||
return collapse(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Collapse value)? collapse,
|
||||
TResult Function(_OpenPage value)? openPage,
|
||||
TResult Function(_CreateApp value)? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (collapse != null) {
|
||||
return collapse(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Collapse implements MenuEvent {
|
||||
const factory Collapse() = _$Collapse;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$OpenPageCopyWith<$Res> {
|
||||
factory _$OpenPageCopyWith(_OpenPage value, $Res Function(_OpenPage) then) =
|
||||
__$OpenPageCopyWithImpl<$Res>;
|
||||
$Res call({PageContext context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
|
||||
implements _$OpenPageCopyWith<$Res> {
|
||||
__$OpenPageCopyWithImpl(_OpenPage _value, $Res Function(_OpenPage) _then)
|
||||
: super(_value, (v) => _then(v as _OpenPage));
|
||||
|
||||
@override
|
||||
_OpenPage get _value => super._value as _OpenPage;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? context = freezed,
|
||||
}) {
|
||||
return _then(_OpenPage(
|
||||
context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as PageContext,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_OpenPage implements _OpenPage {
|
||||
const _$_OpenPage(this.context);
|
||||
|
||||
@override
|
||||
final PageContext context;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuEvent.openPage(context: $context)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _OpenPage &&
|
||||
(identical(other.context, context) ||
|
||||
const DeepCollectionEquality().equals(other.context, context)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(context);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$OpenPageCopyWith<_OpenPage> get copyWith =>
|
||||
__$OpenPageCopyWithImpl<_OpenPage>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(PageContext context) openPage,
|
||||
required TResult Function() createApp,
|
||||
}) {
|
||||
return openPage(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? collapse,
|
||||
TResult Function(PageContext context)? openPage,
|
||||
TResult Function()? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (openPage != null) {
|
||||
return openPage(context);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Collapse value) collapse,
|
||||
required TResult Function(_OpenPage value) openPage,
|
||||
required TResult Function(_CreateApp value) createApp,
|
||||
}) {
|
||||
return openPage(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Collapse value)? collapse,
|
||||
TResult Function(_OpenPage value)? openPage,
|
||||
TResult Function(_CreateApp value)? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (openPage != null) {
|
||||
return openPage(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _OpenPage implements MenuEvent {
|
||||
const factory _OpenPage(PageContext context) = _$_OpenPage;
|
||||
|
||||
PageContext get context => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
_$OpenPageCopyWith<_OpenPage> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$CreateAppCopyWith<$Res> {
|
||||
factory _$CreateAppCopyWith(
|
||||
_CreateApp value, $Res Function(_CreateApp) then) =
|
||||
__$CreateAppCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$CreateAppCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
|
||||
implements _$CreateAppCopyWith<$Res> {
|
||||
__$CreateAppCopyWithImpl(_CreateApp _value, $Res Function(_CreateApp) _then)
|
||||
: super(_value, (v) => _then(v as _CreateApp));
|
||||
|
||||
@override
|
||||
_CreateApp get _value => super._value as _CreateApp;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_CreateApp implements _CreateApp {
|
||||
const _$_CreateApp();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuEvent.createApp()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _CreateApp);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(PageContext context) openPage,
|
||||
required TResult Function() createApp,
|
||||
}) {
|
||||
return createApp();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? collapse,
|
||||
TResult Function(PageContext context)? openPage,
|
||||
TResult Function()? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (createApp != null) {
|
||||
return createApp();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Collapse value) collapse,
|
||||
required TResult Function(_OpenPage value) openPage,
|
||||
required TResult Function(_CreateApp value) createApp,
|
||||
}) {
|
||||
return createApp(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Collapse value)? collapse,
|
||||
TResult Function(_OpenPage value)? openPage,
|
||||
TResult Function(_CreateApp value)? createApp,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (createApp != null) {
|
||||
return createApp(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _CreateApp implements MenuEvent {
|
||||
const factory _CreateApp() = _$_CreateApp;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuStateTearOff {
|
||||
const _$MenuStateTearOff();
|
||||
|
||||
_MenuState call(
|
||||
{required bool isCollapse, required Option<PageContext> pageContext}) {
|
||||
return _MenuState(
|
||||
isCollapse: isCollapse,
|
||||
pageContext: pageContext,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $MenuState = _$MenuStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$MenuState {
|
||||
bool get isCollapse => throw _privateConstructorUsedError;
|
||||
Option<PageContext> get pageContext => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$MenuStateCopyWith<MenuState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $MenuStateCopyWith<$Res> {
|
||||
factory $MenuStateCopyWith(MenuState value, $Res Function(MenuState) then) =
|
||||
_$MenuStateCopyWithImpl<$Res>;
|
||||
$Res call({bool isCollapse, Option<PageContext> pageContext});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> {
|
||||
_$MenuStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
final MenuState _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(MenuState) _then;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? isCollapse = freezed,
|
||||
Object? pageContext = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isCollapse: isCollapse == freezed
|
||||
? _value.isCollapse
|
||||
: isCollapse // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
pageContext: pageContext == freezed
|
||||
? _value.pageContext
|
||||
: pageContext // ignore: cast_nullable_to_non_nullable
|
||||
as Option<PageContext>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> {
|
||||
factory _$MenuStateCopyWith(
|
||||
_MenuState value, $Res Function(_MenuState) then) =
|
||||
__$MenuStateCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({bool isCollapse, Option<PageContext> pageContext});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res>
|
||||
implements _$MenuStateCopyWith<$Res> {
|
||||
__$MenuStateCopyWithImpl(_MenuState _value, $Res Function(_MenuState) _then)
|
||||
: super(_value, (v) => _then(v as _MenuState));
|
||||
|
||||
@override
|
||||
_MenuState get _value => super._value as _MenuState;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? isCollapse = freezed,
|
||||
Object? pageContext = freezed,
|
||||
}) {
|
||||
return _then(_MenuState(
|
||||
isCollapse: isCollapse == freezed
|
||||
? _value.isCollapse
|
||||
: isCollapse // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
pageContext: pageContext == freezed
|
||||
? _value.pageContext
|
||||
: pageContext // ignore: cast_nullable_to_non_nullable
|
||||
as Option<PageContext>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_MenuState implements _MenuState {
|
||||
const _$_MenuState({required this.isCollapse, required this.pageContext});
|
||||
|
||||
@override
|
||||
final bool isCollapse;
|
||||
@override
|
||||
final Option<PageContext> pageContext;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuState(isCollapse: $isCollapse, pageContext: $pageContext)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _MenuState &&
|
||||
(identical(other.isCollapse, isCollapse) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.isCollapse, isCollapse)) &&
|
||||
(identical(other.pageContext, pageContext) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.pageContext, pageContext)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^
|
||||
const DeepCollectionEquality().hash(isCollapse) ^
|
||||
const DeepCollectionEquality().hash(pageContext);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$MenuStateCopyWith<_MenuState> get copyWith =>
|
||||
__$MenuStateCopyWithImpl<_MenuState>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _MenuState implements MenuState {
|
||||
const factory _MenuState(
|
||||
{required bool isCollapse,
|
||||
required Option<PageContext> pageContext}) = _$_MenuState;
|
||||
|
||||
@override
|
||||
bool get isCollapse => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<PageContext> get pageContext => throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$MenuStateCopyWith<_MenuState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
8
app_flowy/lib/home/application/menu/menu_event.dart
Normal file
8
app_flowy/lib/home/application/menu/menu_event.dart
Normal file
@ -0,0 +1,8 @@
|
||||
part of 'menu_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class MenuEvent with _$MenuEvent {
|
||||
const factory MenuEvent.collapse() = Collapse;
|
||||
const factory MenuEvent.openPage(PageContext context) = _OpenPage;
|
||||
const factory MenuEvent.createApp() = _CreateApp;
|
||||
}
|
14
app_flowy/lib/home/application/menu/menu_state.dart
Normal file
14
app_flowy/lib/home/application/menu/menu_state.dart
Normal file
@ -0,0 +1,14 @@
|
||||
part of 'menu_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class MenuState implements _$MenuState {
|
||||
const factory MenuState({
|
||||
required bool isCollapse,
|
||||
required Option<PageContext> pageContext,
|
||||
}) = _MenuState;
|
||||
|
||||
factory MenuState.initial() => MenuState(
|
||||
isCollapse: false,
|
||||
pageContext: none(),
|
||||
);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
part 'home_watcher_event.dart';
|
||||
part 'home_watcher_state.dart';
|
||||
part 'home_watcher_bloc.freezed.dart';
|
||||
|
||||
class HomeWatcherBloc extends Bloc<HomeWatcherEvent, HomeWatcherState> {
|
||||
HomeWatcherBloc() : super(const HomeWatcherState.initial());
|
||||
|
||||
@override
|
||||
Stream<HomeWatcherState> mapEventToState(
|
||||
HomeWatcherEvent event,
|
||||
) async* {
|
||||
yield state;
|
||||
}
|
||||
}
|
@ -0,0 +1,562 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
|
||||
|
||||
part of 'home_watcher_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeWatcherEventTearOff {
|
||||
const _$HomeWatcherEventTearOff();
|
||||
|
||||
_Started started(String workspaceId) {
|
||||
return _Started(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
_Stop stop(String workspaceId) {
|
||||
return _Stop(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $HomeWatcherEvent = _$HomeWatcherEventTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HomeWatcherEvent {
|
||||
String get workspaceId => throw _privateConstructorUsedError;
|
||||
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String workspaceId) started,
|
||||
required TResult Function(String workspaceId) stop,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String workspaceId)? started,
|
||||
TResult Function(String workspaceId)? stop,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Started value) started,
|
||||
required TResult Function(_Stop value) stop,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Started value)? started,
|
||||
TResult Function(_Stop value)? stop,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$HomeWatcherEventCopyWith<HomeWatcherEvent> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HomeWatcherEventCopyWith<$Res> {
|
||||
factory $HomeWatcherEventCopyWith(
|
||||
HomeWatcherEvent value, $Res Function(HomeWatcherEvent) then) =
|
||||
_$HomeWatcherEventCopyWithImpl<$Res>;
|
||||
$Res call({String workspaceId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeWatcherEventCopyWithImpl<$Res>
|
||||
implements $HomeWatcherEventCopyWith<$Res> {
|
||||
_$HomeWatcherEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
final HomeWatcherEvent _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(HomeWatcherEvent) _then;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? workspaceId = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
workspaceId: workspaceId == freezed
|
||||
? _value.workspaceId
|
||||
: workspaceId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$StartedCopyWith<$Res>
|
||||
implements $HomeWatcherEventCopyWith<$Res> {
|
||||
factory _$StartedCopyWith(_Started value, $Res Function(_Started) then) =
|
||||
__$StartedCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({String workspaceId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$StartedCopyWithImpl<$Res> extends _$HomeWatcherEventCopyWithImpl<$Res>
|
||||
implements _$StartedCopyWith<$Res> {
|
||||
__$StartedCopyWithImpl(_Started _value, $Res Function(_Started) _then)
|
||||
: super(_value, (v) => _then(v as _Started));
|
||||
|
||||
@override
|
||||
_Started get _value => super._value as _Started;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? workspaceId = freezed,
|
||||
}) {
|
||||
return _then(_Started(
|
||||
workspaceId == freezed
|
||||
? _value.workspaceId
|
||||
: workspaceId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Started implements _Started {
|
||||
const _$_Started(this.workspaceId);
|
||||
|
||||
@override
|
||||
final String workspaceId;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeWatcherEvent.started(workspaceId: $workspaceId)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _Started &&
|
||||
(identical(other.workspaceId, workspaceId) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.workspaceId, workspaceId)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(workspaceId);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$StartedCopyWith<_Started> get copyWith =>
|
||||
__$StartedCopyWithImpl<_Started>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String workspaceId) started,
|
||||
required TResult Function(String workspaceId) stop,
|
||||
}) {
|
||||
return started(workspaceId);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String workspaceId)? started,
|
||||
TResult Function(String workspaceId)? stop,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (started != null) {
|
||||
return started(workspaceId);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Started value) started,
|
||||
required TResult Function(_Stop value) stop,
|
||||
}) {
|
||||
return started(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Started value)? started,
|
||||
TResult Function(_Stop value)? stop,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (started != null) {
|
||||
return started(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Started implements HomeWatcherEvent {
|
||||
const factory _Started(String workspaceId) = _$_Started;
|
||||
|
||||
@override
|
||||
String get workspaceId => throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$StartedCopyWith<_Started> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$StopCopyWith<$Res> implements $HomeWatcherEventCopyWith<$Res> {
|
||||
factory _$StopCopyWith(_Stop value, $Res Function(_Stop) then) =
|
||||
__$StopCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({String workspaceId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$StopCopyWithImpl<$Res> extends _$HomeWatcherEventCopyWithImpl<$Res>
|
||||
implements _$StopCopyWith<$Res> {
|
||||
__$StopCopyWithImpl(_Stop _value, $Res Function(_Stop) _then)
|
||||
: super(_value, (v) => _then(v as _Stop));
|
||||
|
||||
@override
|
||||
_Stop get _value => super._value as _Stop;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? workspaceId = freezed,
|
||||
}) {
|
||||
return _then(_Stop(
|
||||
workspaceId == freezed
|
||||
? _value.workspaceId
|
||||
: workspaceId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Stop implements _Stop {
|
||||
const _$_Stop(this.workspaceId);
|
||||
|
||||
@override
|
||||
final String workspaceId;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeWatcherEvent.stop(workspaceId: $workspaceId)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _Stop &&
|
||||
(identical(other.workspaceId, workspaceId) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.workspaceId, workspaceId)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(workspaceId);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$StopCopyWith<_Stop> get copyWith =>
|
||||
__$StopCopyWithImpl<_Stop>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String workspaceId) started,
|
||||
required TResult Function(String workspaceId) stop,
|
||||
}) {
|
||||
return stop(workspaceId);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String workspaceId)? started,
|
||||
TResult Function(String workspaceId)? stop,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (stop != null) {
|
||||
return stop(workspaceId);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Started value) started,
|
||||
required TResult Function(_Stop value) stop,
|
||||
}) {
|
||||
return stop(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Started value)? started,
|
||||
TResult Function(_Stop value)? stop,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (stop != null) {
|
||||
return stop(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Stop implements HomeWatcherEvent {
|
||||
const factory _Stop(String workspaceId) = _$_Stop;
|
||||
|
||||
@override
|
||||
String get workspaceId => throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$StopCopyWith<_Stop> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeWatcherStateTearOff {
|
||||
const _$HomeWatcherStateTearOff();
|
||||
|
||||
_Initial initial() {
|
||||
return const _Initial();
|
||||
}
|
||||
|
||||
_Loading loading() {
|
||||
return const _Loading();
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $HomeWatcherState = _$HomeWatcherStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HomeWatcherState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_Loading value) loading,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_Loading value)? loading,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HomeWatcherStateCopyWith<$Res> {
|
||||
factory $HomeWatcherStateCopyWith(
|
||||
HomeWatcherState value, $Res Function(HomeWatcherState) then) =
|
||||
_$HomeWatcherStateCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeWatcherStateCopyWithImpl<$Res>
|
||||
implements $HomeWatcherStateCopyWith<$Res> {
|
||||
_$HomeWatcherStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
final HomeWatcherState _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(HomeWatcherState) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$InitialCopyWith<$Res> {
|
||||
factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
|
||||
__$InitialCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$InitialCopyWithImpl<$Res> extends _$HomeWatcherStateCopyWithImpl<$Res>
|
||||
implements _$InitialCopyWith<$Res> {
|
||||
__$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
|
||||
: super(_value, (v) => _then(v as _Initial));
|
||||
|
||||
@override
|
||||
_Initial get _value => super._value as _Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Initial implements _Initial {
|
||||
const _$_Initial();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeWatcherState.initial()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _Initial);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
}) {
|
||||
return initial();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_Loading value) loading,
|
||||
}) {
|
||||
return initial(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_Loading value)? loading,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Initial implements HomeWatcherState {
|
||||
const factory _Initial() = _$_Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$LoadingCopyWith<$Res> {
|
||||
factory _$LoadingCopyWith(_Loading value, $Res Function(_Loading) then) =
|
||||
__$LoadingCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$LoadingCopyWithImpl<$Res> extends _$HomeWatcherStateCopyWithImpl<$Res>
|
||||
implements _$LoadingCopyWith<$Res> {
|
||||
__$LoadingCopyWithImpl(_Loading _value, $Res Function(_Loading) _then)
|
||||
: super(_value, (v) => _then(v as _Loading));
|
||||
|
||||
@override
|
||||
_Loading get _value => super._value as _Loading;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Loading implements _Loading {
|
||||
const _$_Loading();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeWatcherState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _Loading);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_Loading value) loading,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_Loading value)? loading,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Loading implements HomeWatcherState {
|
||||
const factory _Loading() = _$_Loading;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
part of 'home_watcher_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class HomeWatcherEvent with _$HomeWatcherEvent {
|
||||
const factory HomeWatcherEvent.started(String workspaceId) = _Started;
|
||||
const factory HomeWatcherEvent.stop(String workspaceId) = _Stop;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
part of 'home_watcher_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class HomeWatcherState with _$HomeWatcherState {
|
||||
const factory HomeWatcherState.initial() = _Initial;
|
||||
const factory HomeWatcherState.loading() = _Loading;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
abstract class IAuth {
|
||||
Widget authScreen();
|
||||
}
|
43
app_flowy/lib/home/presentation/home_layout.dart
Normal file
43
app_flowy/lib/home/presentation/home_layout.dart
Normal file
@ -0,0 +1,43 @@
|
||||
import 'package:app_flowy/home/application/home_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_style/time/duration.dart';
|
||||
import 'package:flowy_style/size.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:sized_context/sized_context.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'home_sizes.dart';
|
||||
|
||||
class HomeLayout {
|
||||
late double menuWidth;
|
||||
late bool showMenu;
|
||||
late bool showEditPannel;
|
||||
late double editPannelWidth;
|
||||
late double homePageLOffset;
|
||||
late double homePageROffset;
|
||||
late Duration animDuration;
|
||||
|
||||
HomeLayout(BuildContext context, BoxConstraints homeScreenConstraint) {
|
||||
final homeBlocState = context.read<HomeBloc>().state;
|
||||
|
||||
showEditPannel = homeBlocState.editContext.isSome();
|
||||
|
||||
menuWidth = Sizes.sideBarSm;
|
||||
if (context.widthPx >= PageBreaks.desktop) {
|
||||
menuWidth = Sizes.sideBarLg;
|
||||
}
|
||||
|
||||
// if (menuBlocState.isCollapse) {
|
||||
// showMenu = false;
|
||||
// } else {
|
||||
// showMenu = context.widthPx > PageBreaks.TabletPortrait;
|
||||
// }
|
||||
showMenu = context.widthPx > PageBreaks.tabletPortrait;
|
||||
|
||||
homePageLOffset = showMenu ? menuWidth : 0.0;
|
||||
animDuration = .35.seconds;
|
||||
|
||||
editPannelWidth = HomeSizes.editPannelWidth;
|
||||
homePageROffset = showEditPannel ? editPannelWidth : 0;
|
||||
}
|
||||
}
|
@ -1,15 +1,144 @@
|
||||
import 'package:app_flowy/home/application/home_bloc.dart';
|
||||
import 'package:app_flowy/home/application/watcher/home_watcher_bloc.dart';
|
||||
import 'package:app_flowy/home/domain/page_context.dart';
|
||||
import 'package:app_flowy/home/presentation/widgets/blank_page.dart';
|
||||
import 'package:app_flowy/home/presentation/widgets/edit_pannel/edit_pannel.dart';
|
||||
import 'package:app_flowy/home/presentation/widgets/edit_pannel/pannel_animation.dart';
|
||||
import 'package:app_flowy/home/presentation/widgets/home_top_bar.dart';
|
||||
import 'package:app_flowy/home/presentation/widgets/menu/home_menu.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:flowy_logger/flowy_logger.dart';
|
||||
import 'package:flowy_sdk/protobuf/user_detail.pb.dart';
|
||||
import 'package:flowy_style/styled_container.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
import 'home_layout.dart';
|
||||
import 'widgets/fading_index_stack.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
static GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||
const HomeScreen({Key? key}) : super(key: key);
|
||||
final UserDetail userDetail;
|
||||
const HomeScreen(this.userDetail, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: null,
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<HomeWatcherBloc>(
|
||||
create: (context) => getIt<HomeWatcherBloc>()),
|
||||
BlocProvider<HomeBloc>(create: (context) => getIt<HomeBloc>()),
|
||||
],
|
||||
child: Scaffold(
|
||||
key: HomeScreen.scaffoldKey,
|
||||
body: BlocBuilder<HomeBloc, HomeState>(
|
||||
builder: (context, state) {
|
||||
return StyledContainer(
|
||||
Theme.of(context).colorScheme.background,
|
||||
child: _buildBody(state),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(HomeState state) {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
final layout = HomeLayout(context, constraints);
|
||||
const homePage = HomePage();
|
||||
final menu = _buildHomeMenu(
|
||||
layout: layout,
|
||||
context: context,
|
||||
);
|
||||
final editPannel = _buildEditPannel(
|
||||
homeState: state,
|
||||
layout: layout,
|
||||
context: context,
|
||||
);
|
||||
return _layoutWidgets(
|
||||
layout: layout,
|
||||
homePage: homePage,
|
||||
homeMenu: menu,
|
||||
editPannel: editPannel);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHomeMenu(
|
||||
{required HomeLayout layout, required BuildContext context}) {
|
||||
final homeBloc = context.read<HomeBloc>();
|
||||
Widget homeMenu = HomeMenu(
|
||||
pageContextChanged: (pageContext) {
|
||||
pageContext.fold(
|
||||
() => homeBloc.add(const HomeEvent.setPage(BlankPageContext())),
|
||||
(pageContext) {
|
||||
homeBloc.add(HomeEvent.setPage(pageContext));
|
||||
},
|
||||
);
|
||||
},
|
||||
isCollapseChanged: (isCollapse) {
|
||||
homeBloc.add(HomeEvent.showMenu(!isCollapse));
|
||||
},
|
||||
);
|
||||
homeMenu = RepaintBoundary(child: homeMenu);
|
||||
homeMenu = FocusTraversalGroup(child: homeMenu);
|
||||
return homeMenu;
|
||||
}
|
||||
|
||||
Widget _buildEditPannel(
|
||||
{required HomeState homeState,
|
||||
required BuildContext context,
|
||||
required HomeLayout layout}) {
|
||||
final homeBloc = context.read<HomeBloc>();
|
||||
Widget editPannel = EditPannel(
|
||||
context: homeState.editContext,
|
||||
onEndEdit: () => homeBloc.add(const HomeEvent.dismissEditPannel()),
|
||||
);
|
||||
// editPannel = RepaintBoundary(child: editPannel);
|
||||
// editPannel = FocusTraversalGroup(child: editPannel);
|
||||
return editPannel;
|
||||
}
|
||||
|
||||
Widget _layoutWidgets(
|
||||
{required HomeLayout layout,
|
||||
required Widget homeMenu,
|
||||
required Widget homePage,
|
||||
required Widget editPannel}) {
|
||||
return Stack(
|
||||
children: [
|
||||
homeMenu
|
||||
.animatedPanelX(
|
||||
closeX: -layout.menuWidth,
|
||||
isClosed: !layout.showMenu,
|
||||
)
|
||||
.positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: layout.menuWidth,
|
||||
bottom: 0,
|
||||
animate: true)
|
||||
.animate(layout.animDuration, Curves.easeOut),
|
||||
homePage
|
||||
.constrained(minWidth: 500)
|
||||
.positioned(
|
||||
left: layout.homePageLOffset,
|
||||
right: layout.homePageROffset,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
animate: true)
|
||||
.animate(layout.animDuration, Curves.easeOut),
|
||||
editPannel
|
||||
.animatedPanelX(
|
||||
duration: layout.animDuration.inMilliseconds * 0.001,
|
||||
closeX: layout.editPannelWidth,
|
||||
isClosed: !layout.showEditPannel,
|
||||
)
|
||||
.positioned(
|
||||
right: 0, top: 0, bottom: 0, width: layout.editPannelWidth),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -32,3 +161,51 @@ List<Widget> buildPagesWidget(PageContext pageContext) {
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
static GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||
// final Size size;
|
||||
const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Log.info('HomePage build');
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: const [
|
||||
HomeTopBar(),
|
||||
HomeIndexStack(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeIndexStack extends StatelessWidget {
|
||||
const HomeIndexStack({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<HomeBloc, HomeState>(
|
||||
buildWhen: (p, c) {
|
||||
if (p.pageContext != c.pageContext) {
|
||||
Log.info(
|
||||
'PageContext switch from ${p.pageContext.pageType} to ${c.pageContext.pageType}');
|
||||
}
|
||||
return p.pageContext != c.pageContext;
|
||||
},
|
||||
builder: (context, state) {
|
||||
final pageContext = context.read<HomeBloc>().state.pageContext;
|
||||
return Expanded(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: FocusTraversalGroup(
|
||||
child: FadingIndexedStack(
|
||||
index: pages.indexOf(pageContext.pageType),
|
||||
children: buildPagesWidget(pageContext),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
11
app_flowy/lib/home/presentation/home_sizes.dart
Normal file
11
app_flowy/lib/home/presentation/home_sizes.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class HomeSizes {
|
||||
static double get menuTopBarHeight => 60;
|
||||
static double get menuAddButtonHeight => 60;
|
||||
static double get topBarHeight => 60;
|
||||
static double get editPannelTopBarHeight => 60;
|
||||
static double get editPannelWidth => 400;
|
||||
}
|
||||
|
||||
class HomeInsets {
|
||||
static double get topBarTitlePadding => 12;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
import 'package:app_flowy/home/application/edit_pannel/edit_pannel_bloc.dart';
|
||||
import 'package:app_flowy/home/domain/edit_context.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_style/styled_bar_title.dart';
|
||||
import 'package:flowy_style/styled_close_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../home_sizes.dart';
|
||||
|
||||
class EditPannel extends StatelessWidget {
|
||||
late final EditPannelContext editContext;
|
||||
final VoidCallback onEndEdit;
|
||||
EditPannel(
|
||||
{Key? key,
|
||||
required Option<EditPannelContext> context,
|
||||
required this.onEndEdit})
|
||||
: super(key: key) {
|
||||
editContext = context.fold(() => const BlankEditPannelContext(), (c) => c);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.primaryVariant,
|
||||
child: BlocProvider(
|
||||
create: (context) => getIt<EditPannelBloc>(),
|
||||
child: BlocBuilder<EditPannelBloc, EditPannelState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
EditPannelTopBar(onClose: () => onEndEdit()),
|
||||
Expanded(
|
||||
child: editContext.child,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EditPannelTopBar extends StatelessWidget {
|
||||
final VoidCallback onClose;
|
||||
const EditPannelTopBar({Key? key, required this.onClose}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.editPannelTopBarHeight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const StyleBarTitle(
|
||||
title: 'Title',
|
||||
),
|
||||
const Spacer(),
|
||||
StyleCloseButton(onPressed: onClose),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AnimatedPanel extends StatefulWidget {
|
||||
final bool isClosed;
|
||||
final double closedX;
|
||||
final double closedY;
|
||||
final double duration;
|
||||
final Curve? curve;
|
||||
final Widget? child;
|
||||
|
||||
const AnimatedPanel(
|
||||
{Key? key,
|
||||
this.isClosed = false,
|
||||
this.closedX = 0.0,
|
||||
this.closedY = 0.0,
|
||||
this.duration = 0.0,
|
||||
this.curve,
|
||||
this.child})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_AnimatedPanelState createState() => _AnimatedPanelState();
|
||||
}
|
||||
|
||||
class _AnimatedPanelState extends State<AnimatedPanel> {
|
||||
bool _isHidden = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Offset closePos = Offset(widget.closedX, widget.closedY);
|
||||
double duration = _isHidden && widget.isClosed ? 0 : widget.duration;
|
||||
return TweenAnimationBuilder(
|
||||
curve: widget.curve ?? Curves.easeOut,
|
||||
tween: Tween<Offset>(
|
||||
begin: !widget.isClosed ? Offset.zero : closePos,
|
||||
end: !widget.isClosed ? Offset.zero : closePos,
|
||||
),
|
||||
duration: Duration(milliseconds: (duration * 1000).round()),
|
||||
builder: (_, Offset value, Widget? c) {
|
||||
_isHidden =
|
||||
widget.isClosed && value == Offset(widget.closedX, widget.closedY);
|
||||
return _isHidden
|
||||
? Container()
|
||||
: Transform.translate(offset: value, child: c);
|
||||
},
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension AnimatedPanelExtensions on Widget {
|
||||
Widget animatedPanelX(
|
||||
{double closeX = 0.0,
|
||||
bool? isClosed,
|
||||
double? duration,
|
||||
Curve? curve}) =>
|
||||
animatedPanel(
|
||||
closePos: Offset(closeX, 0),
|
||||
isClosed: isClosed,
|
||||
curve: curve,
|
||||
duration: duration);
|
||||
|
||||
Widget animatedPanelY(
|
||||
{double closeY = 0.0,
|
||||
bool? isClosed,
|
||||
double? duration,
|
||||
Curve? curve}) =>
|
||||
animatedPanel(
|
||||
closePos: Offset(0, closeY),
|
||||
isClosed: isClosed,
|
||||
curve: curve,
|
||||
duration: duration);
|
||||
|
||||
Widget animatedPanel(
|
||||
{required Offset closePos,
|
||||
bool? isClosed,
|
||||
double? duration,
|
||||
Curve? curve}) {
|
||||
return AnimatedPanel(
|
||||
closedX: closePos.dx,
|
||||
closedY: closePos.dy,
|
||||
child: this,
|
||||
isClosed: isClosed ?? false,
|
||||
duration: duration ?? .35,
|
||||
curve: curve);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:time/time.dart';
|
||||
|
||||
class FadingIndexedStack extends StatefulWidget {
|
||||
final int index;
|
||||
final List<Widget> children;
|
||||
final Duration duration;
|
||||
|
||||
const FadingIndexedStack({
|
||||
Key? key,
|
||||
required this.index,
|
||||
required this.children,
|
||||
this.duration = const Duration(
|
||||
milliseconds: 250,
|
||||
),
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_FadingIndexedStackState createState() => _FadingIndexedStackState();
|
||||
}
|
||||
|
||||
class _FadingIndexedStackState extends State<FadingIndexedStack> {
|
||||
double _targetOpacity = 1;
|
||||
|
||||
@override
|
||||
void didUpdateWidget(FadingIndexedStack oldWidget) {
|
||||
if (oldWidget.index == widget.index) return;
|
||||
setState(() => _targetOpacity = 0);
|
||||
Future.delayed(1.milliseconds, () => setState(() => _targetOpacity = 1));
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TweenAnimationBuilder<double>(
|
||||
duration: _targetOpacity > 0 ? widget.duration : 0.milliseconds,
|
||||
tween: Tween(begin: 0, end: _targetOpacity),
|
||||
builder: (_, value, child) {
|
||||
return Opacity(opacity: value, child: child);
|
||||
},
|
||||
child: IndexedStack(index: widget.index, children: widget.children),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
import 'package:app_flowy/home/domain/page_context.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class HomeStackPage extends StatefulWidget {
|
||||
final PageContext pageContext;
|
||||
const HomeStackPage({Key? key, required this.pageContext}) : super(key: key);
|
||||
}
|
51
app_flowy/lib/home/presentation/widgets/home_top_bar.dart
Normal file
51
app_flowy/lib/home/presentation/widgets/home_top_bar.dart
Normal file
@ -0,0 +1,51 @@
|
||||
import 'package:app_flowy/home/application/home_bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../home_sizes.dart';
|
||||
|
||||
class HomeTopBar extends StatelessWidget {
|
||||
const HomeTopBar({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: HomeInsets.topBarTitlePadding),
|
||||
height: HomeSizes.topBarHeight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
HomeTitle(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeTitle extends StatelessWidget {
|
||||
final _editingController = TextEditingController(
|
||||
text: '',
|
||||
);
|
||||
|
||||
HomeTitle({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_editingController.text =
|
||||
context.read<HomeBloc>().state.pageContext.pageTitle;
|
||||
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
controller: _editingController,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(fontSize: 28.0),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Name the view',
|
||||
border: UnderlineInputBorder(borderSide: BorderSide.none),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
class HomeMenuSize {
|
||||
static double get createViewButtonSize => 30;
|
||||
static double get collapseIconSize => 24;
|
||||
}
|
121
app_flowy/lib/home/presentation/widgets/menu/home_menu.dart
Normal file
121
app_flowy/lib/home/presentation/widgets/menu/home_menu.dart
Normal file
@ -0,0 +1,121 @@
|
||||
import 'package:app_flowy/home/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/home/domain/page_context.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../home_sizes.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class HomeMenu extends StatelessWidget {
|
||||
final Function(Option<PageContext>) pageContextChanged;
|
||||
final Function(bool) isCollapseChanged;
|
||||
|
||||
const HomeMenu(
|
||||
{Key? key,
|
||||
required this.pageContextChanged,
|
||||
required this.isCollapseChanged})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<MenuBloc>(create: (context) => getIt<MenuBloc>()),
|
||||
],
|
||||
child: MultiBlocListener(
|
||||
listeners: bind(),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.primaryVariant,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: Insets.sm),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const MenuTopBar(),
|
||||
Container(),
|
||||
const NewAppButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// bind the function passed by ooutter with the bloc listener
|
||||
List<BlocListener<MenuBloc, MenuState>> bind() {
|
||||
return [
|
||||
BlocListener<MenuBloc, MenuState>(
|
||||
listenWhen: (p, c) => p.pageContext != c.pageContext,
|
||||
listener: (context, state) => pageContextChanged(state.pageContext),
|
||||
),
|
||||
BlocListener<MenuBloc, MenuState>(
|
||||
listenWhen: (p, c) => p.isCollapse != c.isCollapse,
|
||||
listener: (context, state) => isCollapseChanged(state.isCollapse),
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class MenuTopBar extends StatelessWidget {
|
||||
const MenuTopBar({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<MenuBloc, MenuState>(
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.menuTopBarHeight,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
'AppFlowy',
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
).constrained(minWidth: 100),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_left),
|
||||
onPressed: () =>
|
||||
context.read<MenuBloc>().add(const MenuEvent.collapse()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NewAppButton extends StatelessWidget {
|
||||
const NewAppButton({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.menuAddButtonHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(Icons.add),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
// Dialogs.show(OkCancelDialog(
|
||||
// title: "No Connection",
|
||||
// message:
|
||||
// "It appears your device is offline. Please check your connection and try again.",
|
||||
// onOkPressed: () => AppGlobals.nav.pop(),
|
||||
// ));
|
||||
},
|
||||
child: const Text('New App',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20)),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export 'home_menu.dart';
|
||||
export 'hom_menu_size.dart';
|
@ -1,6 +1,6 @@
|
||||
import 'package:app_flowy/startup/launch.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/welcome/infrastructure/deps_impl.dart';
|
||||
import 'package:app_flowy/welcome/infrastructure/interface_impl.dart';
|
||||
import 'package:flowy_sdk/flowy_sdk.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
|
@ -16,7 +16,7 @@ enum LaunchTaskType {
|
||||
/// some nonresident indispensable task in app launching task.
|
||||
abstract class LaunchTask {
|
||||
LaunchTaskType get type => LaunchTaskType.dataProcessing;
|
||||
void initialize(LaunchContext context);
|
||||
Future<void> initialize(LaunchContext context);
|
||||
}
|
||||
|
||||
class AppLauncher {
|
||||
@ -30,10 +30,10 @@ class AppLauncher {
|
||||
tasks.add(task);
|
||||
}
|
||||
|
||||
void launch() {
|
||||
void launch() async {
|
||||
final context = LaunchContext(getIt, env);
|
||||
for (var task in tasks) {
|
||||
task.initialize(context);
|
||||
await task.initialize(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,12 @@ class AppWidgetTask extends LaunchTask {
|
||||
LaunchTaskType get type => LaunchTaskType.appLauncher;
|
||||
|
||||
@override
|
||||
void initialize(LaunchContext context) {
|
||||
Future<void> initialize(LaunchContext context) {
|
||||
final widget = context.getIt<AppFactory>().create();
|
||||
final app = AppWidget(child: widget);
|
||||
runApp(app);
|
||||
|
||||
return Future(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ class RustSDKInitTask extends LaunchTask {
|
||||
LaunchTaskType get type => LaunchTaskType.dataProcessing;
|
||||
|
||||
@override
|
||||
void initialize(LaunchContext context) async {
|
||||
Future<void> initialize(LaunchContext context) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
Bloc.observer = ApplicationBlocObserver();
|
||||
@ -31,6 +31,8 @@ class RustSDKInitTask extends LaunchTask {
|
||||
default:
|
||||
assert(false, 'Unsupported env');
|
||||
}
|
||||
|
||||
return Future(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:app_flowy/welcome/domain/auth_state.dart';
|
||||
import 'package:app_flowy/welcome/domain/deps.dart';
|
||||
import 'package:app_flowy/welcome/domain/interface.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
@ -8,18 +8,14 @@ part 'welcome_state.dart';
|
||||
part 'welcome_bloc.freezed.dart';
|
||||
|
||||
class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
|
||||
final IWelcomeAuth authCheck;
|
||||
WelcomeBloc(this.authCheck) : super(WelcomeState.initial());
|
||||
final IWelcomeAuth authImpl;
|
||||
WelcomeBloc(this.authImpl) : super(WelcomeState.initial());
|
||||
|
||||
@override
|
||||
Stream<WelcomeState> mapEventToState(WelcomeEvent event) async* {
|
||||
yield* event.map(
|
||||
check: (val) async* {
|
||||
add(const WelcomeEvent.authCheck());
|
||||
yield state;
|
||||
},
|
||||
authCheck: (val) async* {
|
||||
final authState = await authCheck.getAuthState();
|
||||
getUser: (val) async* {
|
||||
final authState = await authImpl.currentUserState();
|
||||
yield state.copyWith(auth: authState);
|
||||
},
|
||||
);
|
||||
|
@ -16,12 +16,8 @@ final _privateConstructorUsedError = UnsupportedError(
|
||||
class _$WelcomeEventTearOff {
|
||||
const _$WelcomeEventTearOff();
|
||||
|
||||
_Check check() {
|
||||
return const _Check();
|
||||
}
|
||||
|
||||
_AuthCheck authCheck() {
|
||||
return const _AuthCheck();
|
||||
_GetUser getUser() {
|
||||
return const _GetUser();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,27 +28,23 @@ const $WelcomeEvent = _$WelcomeEventTearOff();
|
||||
mixin _$WelcomeEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() check,
|
||||
required TResult Function() authCheck,
|
||||
required TResult Function() getUser,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? check,
|
||||
TResult Function()? authCheck,
|
||||
TResult Function()? getUser,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Check value) check,
|
||||
required TResult Function(_AuthCheck value) authCheck,
|
||||
required TResult Function(_GetUser value) getUser,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Check value)? check,
|
||||
TResult Function(_AuthCheck value)? authCheck,
|
||||
TResult Function(_GetUser value)? getUser,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -75,34 +67,34 @@ class _$WelcomeEventCopyWithImpl<$Res> implements $WelcomeEventCopyWith<$Res> {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$CheckCopyWith<$Res> {
|
||||
factory _$CheckCopyWith(_Check value, $Res Function(_Check) then) =
|
||||
__$CheckCopyWithImpl<$Res>;
|
||||
abstract class _$GetUserCopyWith<$Res> {
|
||||
factory _$GetUserCopyWith(_GetUser value, $Res Function(_GetUser) then) =
|
||||
__$GetUserCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$CheckCopyWithImpl<$Res> extends _$WelcomeEventCopyWithImpl<$Res>
|
||||
implements _$CheckCopyWith<$Res> {
|
||||
__$CheckCopyWithImpl(_Check _value, $Res Function(_Check) _then)
|
||||
: super(_value, (v) => _then(v as _Check));
|
||||
class __$GetUserCopyWithImpl<$Res> extends _$WelcomeEventCopyWithImpl<$Res>
|
||||
implements _$GetUserCopyWith<$Res> {
|
||||
__$GetUserCopyWithImpl(_GetUser _value, $Res Function(_GetUser) _then)
|
||||
: super(_value, (v) => _then(v as _GetUser));
|
||||
|
||||
@override
|
||||
_Check get _value => super._value as _Check;
|
||||
_GetUser get _value => super._value as _GetUser;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Check implements _Check {
|
||||
const _$_Check();
|
||||
class _$_GetUser implements _GetUser {
|
||||
const _$_GetUser();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WelcomeEvent.check()';
|
||||
return 'WelcomeEvent.getUser()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _Check);
|
||||
return identical(this, other) || (other is _GetUser);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -111,21 +103,19 @@ class _$_Check implements _Check {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() check,
|
||||
required TResult Function() authCheck,
|
||||
required TResult Function() getUser,
|
||||
}) {
|
||||
return check();
|
||||
return getUser();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? check,
|
||||
TResult Function()? authCheck,
|
||||
TResult Function()? getUser,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (check != null) {
|
||||
return check();
|
||||
if (getUser != null) {
|
||||
return getUser();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -133,112 +123,26 @@ class _$_Check implements _Check {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Check value) check,
|
||||
required TResult Function(_AuthCheck value) authCheck,
|
||||
required TResult Function(_GetUser value) getUser,
|
||||
}) {
|
||||
return check(this);
|
||||
return getUser(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Check value)? check,
|
||||
TResult Function(_AuthCheck value)? authCheck,
|
||||
TResult Function(_GetUser value)? getUser,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (check != null) {
|
||||
return check(this);
|
||||
if (getUser != null) {
|
||||
return getUser(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Check implements WelcomeEvent {
|
||||
const factory _Check() = _$_Check;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$AuthCheckCopyWith<$Res> {
|
||||
factory _$AuthCheckCopyWith(
|
||||
_AuthCheck value, $Res Function(_AuthCheck) then) =
|
||||
__$AuthCheckCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$AuthCheckCopyWithImpl<$Res> extends _$WelcomeEventCopyWithImpl<$Res>
|
||||
implements _$AuthCheckCopyWith<$Res> {
|
||||
__$AuthCheckCopyWithImpl(_AuthCheck _value, $Res Function(_AuthCheck) _then)
|
||||
: super(_value, (v) => _then(v as _AuthCheck));
|
||||
|
||||
@override
|
||||
_AuthCheck get _value => super._value as _AuthCheck;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_AuthCheck implements _AuthCheck {
|
||||
const _$_AuthCheck();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WelcomeEvent.authCheck()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _AuthCheck);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() check,
|
||||
required TResult Function() authCheck,
|
||||
}) {
|
||||
return authCheck();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? check,
|
||||
TResult Function()? authCheck,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (authCheck != null) {
|
||||
return authCheck();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Check value) check,
|
||||
required TResult Function(_AuthCheck value) authCheck,
|
||||
}) {
|
||||
return authCheck(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Check value)? check,
|
||||
TResult Function(_AuthCheck value)? authCheck,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (authCheck != null) {
|
||||
return authCheck(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AuthCheck implements WelcomeEvent {
|
||||
const factory _AuthCheck() = _$_AuthCheck;
|
||||
abstract class _GetUser implements WelcomeEvent {
|
||||
const factory _GetUser() = _$_GetUser;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
@ -2,6 +2,5 @@ part of 'welcome_bloc.dart';
|
||||
|
||||
@freezed
|
||||
abstract class WelcomeEvent with _$WelcomeEvent {
|
||||
const factory WelcomeEvent.check() = _Check;
|
||||
const factory WelcomeEvent.authCheck() = _AuthCheck;
|
||||
const factory WelcomeEvent.getUser() = _GetUser;
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ abstract class WelcomeState implements _$WelcomeState {
|
||||
}) = _WelcomeState;
|
||||
|
||||
factory WelcomeState.initial() => const WelcomeState(
|
||||
auth: AuthState.unauthenticated(),
|
||||
auth: AuthState.initial(),
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
import 'package:flowy_sdk/protobuf/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/user_detail.pb.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
part 'auth_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class AuthState with _$AuthState {
|
||||
const factory AuthState.authenticated() = Authenticated;
|
||||
const factory AuthState.unauthenticated() = Unauthenticated;
|
||||
const factory AuthState.authenticated(UserDetail userDetail) = Authenticated;
|
||||
const factory AuthState.unauthenticated(UserError error) = Unauthenticated;
|
||||
const factory AuthState.initial() = _Initial;
|
||||
}
|
||||
|
@ -16,12 +16,20 @@ final _privateConstructorUsedError = UnsupportedError(
|
||||
class _$AuthStateTearOff {
|
||||
const _$AuthStateTearOff();
|
||||
|
||||
Authenticated authenticated() {
|
||||
return const Authenticated();
|
||||
Authenticated authenticated(UserDetail userDetail) {
|
||||
return Authenticated(
|
||||
userDetail,
|
||||
);
|
||||
}
|
||||
|
||||
Unauthenticated unauthenticated() {
|
||||
return const Unauthenticated();
|
||||
Unauthenticated unauthenticated(UserError error) {
|
||||
return Unauthenticated(
|
||||
error,
|
||||
);
|
||||
}
|
||||
|
||||
_Initial initial() {
|
||||
return const _Initial();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,14 +40,16 @@ const $AuthState = _$AuthStateTearOff();
|
||||
mixin _$AuthState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() authenticated,
|
||||
required TResult Function() unauthenticated,
|
||||
required TResult Function(UserDetail userDetail) authenticated,
|
||||
required TResult Function(UserError error) unauthenticated,
|
||||
required TResult Function() initial,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? authenticated,
|
||||
TResult Function()? unauthenticated,
|
||||
TResult Function(UserDetail userDetail)? authenticated,
|
||||
TResult Function(UserError error)? unauthenticated,
|
||||
TResult Function()? initial,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -47,12 +57,14 @@ mixin _$AuthState {
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Authenticated value) authenticated,
|
||||
required TResult Function(Unauthenticated value) unauthenticated,
|
||||
required TResult Function(_Initial value) initial,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Authenticated value)? authenticated,
|
||||
TResult Function(Unauthenticated value)? unauthenticated,
|
||||
TResult Function(_Initial value)? initial,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -78,6 +90,7 @@ abstract class $AuthenticatedCopyWith<$Res> {
|
||||
factory $AuthenticatedCopyWith(
|
||||
Authenticated value, $Res Function(Authenticated) then) =
|
||||
_$AuthenticatedCopyWithImpl<$Res>;
|
||||
$Res call({UserDetail userDetail});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -89,44 +102,71 @@ class _$AuthenticatedCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
Authenticated get _value => super._value as Authenticated;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? userDetail = freezed,
|
||||
}) {
|
||||
return _then(Authenticated(
|
||||
userDetail == freezed
|
||||
? _value.userDetail
|
||||
: userDetail // ignore: cast_nullable_to_non_nullable
|
||||
as UserDetail,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$Authenticated implements Authenticated {
|
||||
const _$Authenticated();
|
||||
const _$Authenticated(this.userDetail);
|
||||
|
||||
@override
|
||||
final UserDetail userDetail;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.authenticated()';
|
||||
return 'AuthState.authenticated(userDetail: $userDetail)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is Authenticated);
|
||||
return identical(this, other) ||
|
||||
(other is Authenticated &&
|
||||
(identical(other.userDetail, userDetail) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.userDetail, userDetail)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(userDetail);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
$AuthenticatedCopyWith<Authenticated> get copyWith =>
|
||||
_$AuthenticatedCopyWithImpl<Authenticated>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() authenticated,
|
||||
required TResult Function() unauthenticated,
|
||||
required TResult Function(UserDetail userDetail) authenticated,
|
||||
required TResult Function(UserError error) unauthenticated,
|
||||
required TResult Function() initial,
|
||||
}) {
|
||||
return authenticated();
|
||||
return authenticated(userDetail);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? authenticated,
|
||||
TResult Function()? unauthenticated,
|
||||
TResult Function(UserDetail userDetail)? authenticated,
|
||||
TResult Function(UserError error)? unauthenticated,
|
||||
TResult Function()? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (authenticated != null) {
|
||||
return authenticated();
|
||||
return authenticated(userDetail);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -136,6 +176,7 @@ class _$Authenticated implements Authenticated {
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Authenticated value) authenticated,
|
||||
required TResult Function(Unauthenticated value) unauthenticated,
|
||||
required TResult Function(_Initial value) initial,
|
||||
}) {
|
||||
return authenticated(this);
|
||||
}
|
||||
@ -145,6 +186,7 @@ class _$Authenticated implements Authenticated {
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Authenticated value)? authenticated,
|
||||
TResult Function(Unauthenticated value)? unauthenticated,
|
||||
TResult Function(_Initial value)? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (authenticated != null) {
|
||||
@ -155,7 +197,12 @@ class _$Authenticated implements Authenticated {
|
||||
}
|
||||
|
||||
abstract class Authenticated implements AuthState {
|
||||
const factory Authenticated() = _$Authenticated;
|
||||
const factory Authenticated(UserDetail userDetail) = _$Authenticated;
|
||||
|
||||
UserDetail get userDetail => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$AuthenticatedCopyWith<Authenticated> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -163,6 +210,7 @@ abstract class $UnauthenticatedCopyWith<$Res> {
|
||||
factory $UnauthenticatedCopyWith(
|
||||
Unauthenticated value, $Res Function(Unauthenticated) then) =
|
||||
_$UnauthenticatedCopyWithImpl<$Res>;
|
||||
$Res call({UserError error});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -174,44 +222,70 @@ class _$UnauthenticatedCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
Unauthenticated get _value => super._value as Unauthenticated;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? error = freezed,
|
||||
}) {
|
||||
return _then(Unauthenticated(
|
||||
error == freezed
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as UserError,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$Unauthenticated implements Unauthenticated {
|
||||
const _$Unauthenticated();
|
||||
const _$Unauthenticated(this.error);
|
||||
|
||||
@override
|
||||
final UserError error;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.unauthenticated()';
|
||||
return 'AuthState.unauthenticated(error: $error)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is Unauthenticated);
|
||||
return identical(this, other) ||
|
||||
(other is Unauthenticated &&
|
||||
(identical(other.error, error) ||
|
||||
const DeepCollectionEquality().equals(other.error, error)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(error);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
$UnauthenticatedCopyWith<Unauthenticated> get copyWith =>
|
||||
_$UnauthenticatedCopyWithImpl<Unauthenticated>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() authenticated,
|
||||
required TResult Function() unauthenticated,
|
||||
required TResult Function(UserDetail userDetail) authenticated,
|
||||
required TResult Function(UserError error) unauthenticated,
|
||||
required TResult Function() initial,
|
||||
}) {
|
||||
return unauthenticated();
|
||||
return unauthenticated(error);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? authenticated,
|
||||
TResult Function()? unauthenticated,
|
||||
TResult Function(UserDetail userDetail)? authenticated,
|
||||
TResult Function(UserError error)? unauthenticated,
|
||||
TResult Function()? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (unauthenticated != null) {
|
||||
return unauthenticated();
|
||||
return unauthenticated(error);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -221,6 +295,7 @@ class _$Unauthenticated implements Unauthenticated {
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Authenticated value) authenticated,
|
||||
required TResult Function(Unauthenticated value) unauthenticated,
|
||||
required TResult Function(_Initial value) initial,
|
||||
}) {
|
||||
return unauthenticated(this);
|
||||
}
|
||||
@ -230,6 +305,7 @@ class _$Unauthenticated implements Unauthenticated {
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Authenticated value)? authenticated,
|
||||
TResult Function(Unauthenticated value)? unauthenticated,
|
||||
TResult Function(_Initial value)? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (unauthenticated != null) {
|
||||
@ -240,5 +316,97 @@ class _$Unauthenticated implements Unauthenticated {
|
||||
}
|
||||
|
||||
abstract class Unauthenticated implements AuthState {
|
||||
const factory Unauthenticated() = _$Unauthenticated;
|
||||
const factory Unauthenticated(UserError error) = _$Unauthenticated;
|
||||
|
||||
UserError get error => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$UnauthenticatedCopyWith<Unauthenticated> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$InitialCopyWith<$Res> {
|
||||
factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
|
||||
__$InitialCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$InitialCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res>
|
||||
implements _$InitialCopyWith<$Res> {
|
||||
__$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
|
||||
: super(_value, (v) => _then(v as _Initial));
|
||||
|
||||
@override
|
||||
_Initial get _value => super._value as _Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Initial implements _Initial {
|
||||
const _$_Initial();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.initial()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _Initial);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(UserDetail userDetail) authenticated,
|
||||
required TResult Function(UserError error) unauthenticated,
|
||||
required TResult Function() initial,
|
||||
}) {
|
||||
return initial();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(UserDetail userDetail)? authenticated,
|
||||
TResult Function(UserError error)? unauthenticated,
|
||||
TResult Function()? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Authenticated value) authenticated,
|
||||
required TResult Function(Unauthenticated value) unauthenticated,
|
||||
required TResult Function(_Initial value) initial,
|
||||
}) {
|
||||
return initial(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Authenticated value)? authenticated,
|
||||
TResult Function(Unauthenticated value)? unauthenticated,
|
||||
TResult Function(_Initial value)? initial,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Initial implements AuthState {
|
||||
const factory _Initial() = _$_Initial;
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'auth_state.dart';
|
||||
|
||||
abstract class IWelcomeAuth {
|
||||
Future<AuthState> getAuthState();
|
||||
}
|
||||
|
||||
abstract class IWelcomeRoute {
|
||||
Widget signIn();
|
||||
Widget home();
|
||||
}
|
13
app_flowy/lib/welcome/domain/interface.dart
Normal file
13
app_flowy/lib/welcome/domain/interface.dart
Normal file
@ -0,0 +1,13 @@
|
||||
import 'package:flowy_sdk/protobuf/user_detail.pb.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'auth_state.dart';
|
||||
|
||||
abstract class IWelcomeAuth {
|
||||
Future<AuthState> currentUserState();
|
||||
}
|
||||
|
||||
abstract class IWelcomeRoute {
|
||||
Widget pushSignInScreen();
|
||||
Widget pushHomeScreen(UserDetail userDetail);
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
import 'package:app_flowy/home/presentation/home_screen.dart';
|
||||
import 'package:app_flowy/welcome/application/welcome_bloc.dart';
|
||||
import 'package:app_flowy/welcome/domain/auth_state.dart';
|
||||
import 'package:app_flowy/welcome/domain/deps.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:time/time.dart';
|
||||
|
||||
class Welcome {
|
||||
static Future<void> dependencyResolved(GetIt getIt) async {
|
||||
getIt.registerFactory<IWelcomeAuth>(() => AuthCheck());
|
||||
getIt.registerFactory<IWelcomeRoute>(() => WelcomeRoute());
|
||||
|
||||
getIt
|
||||
.registerFactory<WelcomeBloc>(() => WelcomeBloc(getIt<IWelcomeAuth>()));
|
||||
}
|
||||
}
|
||||
|
||||
class AuthCheck implements IWelcomeAuth {
|
||||
@override
|
||||
Future<AuthState> getAuthState() async {
|
||||
return Future<AuthState>.delayed(3.0.seconds, () {
|
||||
return const AuthState.authenticated();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class WelcomeRoute implements IWelcomeRoute {
|
||||
@override
|
||||
Widget home() {
|
||||
return const HomeScreen();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget signIn() {
|
||||
return Container();
|
||||
}
|
||||
}
|
61
app_flowy/lib/welcome/infrastructure/interface_impl.dart
Normal file
61
app_flowy/lib/welcome/infrastructure/interface_impl.dart
Normal file
@ -0,0 +1,61 @@
|
||||
import 'package:app_flowy/home/application/edit_pannel/edit_pannel_bloc.dart';
|
||||
import 'package:app_flowy/home/application/home_bloc.dart';
|
||||
import 'package:app_flowy/home/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/home/application/watcher/home_watcher_bloc.dart';
|
||||
import 'package:app_flowy/home/presentation/home_screen.dart';
|
||||
import 'package:app_flowy/welcome/application/welcome_bloc.dart';
|
||||
import 'package:app_flowy/welcome/domain/auth_state.dart';
|
||||
import 'package:app_flowy/welcome/domain/interface.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/user_detail.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
class Welcome {
|
||||
static Future<void> dependencyResolved(GetIt getIt) async {
|
||||
getIt.registerFactory<IWelcomeAuth>(() => WelcomeAuthImpl());
|
||||
getIt.registerFactory<IWelcomeRoute>(() => WelcomeRoute());
|
||||
getIt.registerFactory<HomeBloc>(() => HomeBloc());
|
||||
getIt.registerFactory<HomeWatcherBloc>(() => HomeWatcherBloc());
|
||||
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
|
||||
|
||||
getIt.registerFactory<MenuBloc>(() => MenuBloc());
|
||||
|
||||
getIt
|
||||
.registerFactory<WelcomeBloc>(() => WelcomeBloc(getIt<IWelcomeAuth>()));
|
||||
}
|
||||
}
|
||||
|
||||
class WelcomeAuthImpl implements IWelcomeAuth {
|
||||
@override
|
||||
Future<AuthState> currentUserState() {
|
||||
final result = UserEventGetStatus().send();
|
||||
return result.then((result) {
|
||||
return result.fold(
|
||||
(userDetail) {
|
||||
return AuthState.authenticated(userDetail);
|
||||
},
|
||||
(userError) {
|
||||
return AuthState.unauthenticated(userError);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class WelcomeRoute implements IWelcomeRoute {
|
||||
@override
|
||||
Widget pushHomeScreen(UserDetail user) {
|
||||
return HomeScreen(user);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget pushSignInScreen() {
|
||||
return Container(
|
||||
width: 100,
|
||||
height: 100,
|
||||
color: Colors.red,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import 'package:app_flowy/welcome/domain/deps.dart';
|
||||
import 'package:app_flowy/welcome/presentation/widgets/body.dart';
|
||||
import 'package:app_flowy/welcome/domain/interface.dart';
|
||||
import 'package:app_flowy/welcome/domain/auth_state.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/welcome/application/welcome_bloc.dart';
|
||||
import 'package:flowy_logger/flowy_logger.dart';
|
||||
import 'package:flowy_style/route/animation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -14,16 +15,15 @@ class WelcomeScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) {
|
||||
return getIt<WelcomeBloc>()..add(const WelcomeEvent.check());
|
||||
return getIt<WelcomeBloc>()..add(const WelcomeEvent.getUser());
|
||||
},
|
||||
child: Scaffold(
|
||||
body: BlocListener<WelcomeBloc, WelcomeState>(
|
||||
listener: (context, state) {
|
||||
state.auth.map(
|
||||
authenticated: (_) =>
|
||||
_pushToScreen(context, getIt<IWelcomeRoute>().home()),
|
||||
unauthenticated: (_) =>
|
||||
_pushToScreen(context, getIt<IWelcomeRoute>().signIn()),
|
||||
authenticated: (r) => _handleAuthenticated(context, r),
|
||||
unauthenticated: (r) => _handleUnauthenticated(context, r),
|
||||
initial: (r) => {},
|
||||
);
|
||||
},
|
||||
child: const Body(),
|
||||
@ -34,11 +34,46 @@ class WelcomeScreen extends StatelessWidget {
|
||||
|
||||
void _pushToScreen(BuildContext context, Widget screen) {
|
||||
/// Let the splash view sit for a bit. Mainly for aesthetics and to ensure a smooth intro animation.
|
||||
Future<void>.delayed(1.0.seconds, () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRoutes.fade(
|
||||
() => screen, RouteDurations.slow.inMilliseconds * .001));
|
||||
});
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRoutes.fade(
|
||||
() => screen, RouteDurations.slow.inMilliseconds * .001));
|
||||
}
|
||||
|
||||
void _handleAuthenticated(BuildContext context, Authenticated result) {
|
||||
_pushToScreen(
|
||||
context, getIt<IWelcomeRoute>().pushHomeScreen(result.userDetail));
|
||||
}
|
||||
|
||||
void _handleUnauthenticated(BuildContext context, Unauthenticated result) {
|
||||
Log.error(result.error);
|
||||
|
||||
_pushToScreen(context, getIt<IWelcomeRoute>().pushSignInScreen());
|
||||
}
|
||||
}
|
||||
|
||||
class Body extends StatelessWidget {
|
||||
const Body({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
image: const AssetImage(
|
||||
'assets/images/appflowy_launch_splash.jpg')),
|
||||
const CircularProgressIndicator.adaptive(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Body extends StatelessWidget {
|
||||
const Body({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
image: const AssetImage(
|
||||
'assets/images/appflowy_launch_splash.jpg')),
|
||||
const CircularProgressIndicator.adaptive(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.7.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -28,7 +28,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -94,7 +94,7 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -148,7 +148,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -14,7 +14,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.7.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -35,7 +35,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -91,7 +91,7 @@ packages:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
version: "6.1.2"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -200,7 +200,7 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -282,7 +282,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.1"
|
||||
time:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -317,7 +317,7 @@ packages:
|
||||
name: vm_service
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "7.1.0"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -2,15 +2,12 @@ export 'package:async/async.dart';
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
// import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'dart:ffi';
|
||||
import 'ffi/ffi.dart' as ffi;
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
import 'package:flowy_sdk/protobuf.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
|
||||
class FlowySDK {
|
||||
static const MethodChannel _channel = MethodChannel('flowy_sdk');
|
||||
static Future<String> get platformVersion async {
|
||||
@ -24,21 +21,6 @@ class FlowySDK {
|
||||
|
||||
Future<void> init(Directory sdkDir) async {
|
||||
ffi.store_dart_post_cobject(NativeApi.postCObject);
|
||||
|
||||
ffi.init_sdk(sdkDir.path.toNativeUtf8());
|
||||
|
||||
final params = SignInRequest.create();
|
||||
params.email = "nathan.fu@gmail.com";
|
||||
params.password = "Helloworld!2";
|
||||
Either<UserDetail, UserError> resp = await UserEventSignIn(params).send();
|
||||
|
||||
resp.fold(
|
||||
(result) {
|
||||
print(result);
|
||||
},
|
||||
(error) {
|
||||
print(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Auto-generated, do not edit
|
||||
// Auto-generated, do not edit
|
||||
export 'protobuf/kv.pb.dart';
|
||||
export 'protobuf/ffi_response.pb.dart';
|
||||
export 'protobuf/ffi_request.pb.dart';
|
||||
export 'protobuf/user_status.pb.dart';
|
||||
export 'protobuf/sign_up.pb.dart';
|
||||
export 'protobuf/sign_in.pb.dart';
|
||||
export 'protobuf/user_table.pb.dart';
|
||||
export 'protobuf/errors.pb.dart';
|
||||
export 'protobuf/user_detail.pb.dart';
|
||||
export 'protobuf/event.pb.dart';
|
||||
|
@ -1,6 +1,6 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: user_status.proto
|
||||
// source: user_detail.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
||||
@ -9,9 +9,9 @@ import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
import 'user_status.pbenum.dart';
|
||||
import 'user_detail.pbenum.dart';
|
||||
|
||||
export 'user_status.pbenum.dart';
|
||||
export 'user_detail.pbenum.dart';
|
||||
|
||||
class UserDetail extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserDetail', createEmptyInstance: create)
|
@ -1,6 +1,6 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: user_status.proto
|
||||
// source: user_detail.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
@ -1,6 +1,6 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: user_status.proto
|
||||
// source: user_detail.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
@ -1,9 +1,9 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: user_status.proto
|
||||
// source: user_detail.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
||||
|
||||
export 'user_status.pb.dart';
|
||||
export 'user_detail.pb.dart';
|
||||
|
@ -28,7 +28,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.7.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -105,7 +105,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -325,7 +325,7 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -449,7 +449,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.1"
|
||||
time:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -0,0 +1,143 @@
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flowy_style/text_style.dart';
|
||||
import 'package:flowy_style/theme.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BaseStyledButton extends StatefulWidget {
|
||||
final Widget child;
|
||||
final VoidCallback? onPressed;
|
||||
final Function(bool)? onFocusChanged;
|
||||
final Function(bool)? onHighlightChanged;
|
||||
final Color? bgColor;
|
||||
final Color? focusColor;
|
||||
final Color? hoverColor;
|
||||
final Color? downColor;
|
||||
final EdgeInsets? contentPadding;
|
||||
final double? minWidth;
|
||||
final double? minHeight;
|
||||
final double? borderRadius;
|
||||
final bool useBtnText;
|
||||
final bool autoFocus;
|
||||
|
||||
final ShapeBorder? shape;
|
||||
|
||||
final Color outlineColor;
|
||||
|
||||
const BaseStyledButton({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.onPressed,
|
||||
this.onFocusChanged,
|
||||
this.onHighlightChanged,
|
||||
this.bgColor,
|
||||
this.focusColor,
|
||||
this.contentPadding,
|
||||
this.minWidth,
|
||||
this.minHeight,
|
||||
this.borderRadius,
|
||||
this.hoverColor,
|
||||
this.downColor,
|
||||
this.shape,
|
||||
this.useBtnText = true,
|
||||
this.autoFocus = false,
|
||||
this.outlineColor = Colors.transparent,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BaseStyledBtnState createState() => _BaseStyledBtnState();
|
||||
}
|
||||
|
||||
class _BaseStyledBtnState extends State<BaseStyledButton> {
|
||||
late FocusNode _focusNode;
|
||||
bool _isFocused = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_focusNode = FocusNode(debugLabel: '', canRequestFocus: true);
|
||||
_focusNode.addListener(() {
|
||||
if (_focusNode.hasFocus != _isFocused) {
|
||||
setState(() => _isFocused = _focusNode.hasFocus);
|
||||
widget.onFocusChanged?.call(_isFocused);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: widget.bgColor ?? theme.surface,
|
||||
borderRadius: BorderRadius.circular(widget.borderRadius ?? Corners.s5),
|
||||
boxShadow: _isFocused
|
||||
? [
|
||||
BoxShadow(
|
||||
color: theme.focus.withOpacity(0.25),
|
||||
offset: Offset.zero,
|
||||
blurRadius: 8.0,
|
||||
spreadRadius: 0.0),
|
||||
BoxShadow(
|
||||
color: widget.bgColor ?? theme.surface,
|
||||
offset: Offset.zero,
|
||||
blurRadius: 8.0,
|
||||
spreadRadius: -4.0),
|
||||
]
|
||||
: [],
|
||||
),
|
||||
foregroundDecoration: _isFocused
|
||||
? ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
width: 1.8,
|
||||
color: theme.focus,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(widget.borderRadius ?? Corners.s5),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: RawMaterialButton(
|
||||
focusNode: _focusNode,
|
||||
autofocus: widget.autoFocus,
|
||||
textStyle: widget.useBtnText ? TextStyles.Btn : null,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
visualDensity: VisualDensity.compact,
|
||||
splashColor: Colors.transparent,
|
||||
mouseCursor: SystemMouseCursors.click,
|
||||
elevation: 0,
|
||||
hoverElevation: 0,
|
||||
highlightElevation: 0,
|
||||
focusElevation: 0,
|
||||
fillColor: Colors.transparent,
|
||||
hoverColor: widget.hoverColor ?? theme.surface,
|
||||
highlightColor: widget.downColor ?? theme.accent1.withOpacity(.1),
|
||||
focusColor: widget.focusColor ?? Colors.grey.withOpacity(0.35),
|
||||
child: Opacity(
|
||||
child: Padding(
|
||||
padding: widget.contentPadding ?? EdgeInsets.all(Insets.m),
|
||||
child: widget.child,
|
||||
),
|
||||
opacity: widget.onPressed != null ? 1 : .7,
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
minHeight: widget.minHeight ?? 0, minWidth: widget.minWidth ?? 0),
|
||||
onPressed: widget.onPressed,
|
||||
shape: widget.shape ??
|
||||
RoundedRectangleBorder(
|
||||
side: BorderSide(color: widget.outlineColor, width: 1.5),
|
||||
borderRadius:
|
||||
BorderRadius.circular(widget.borderRadius ?? Corners.s5)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flowy_style/spacing.dart';
|
||||
import 'package:flowy_style/strings.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'primary_button.dart';
|
||||
import 'secondary_button.dart';
|
||||
|
||||
class OkCancelButton extends StatelessWidget {
|
||||
final VoidCallback? onOkPressed;
|
||||
final VoidCallback? onCancelPressed;
|
||||
final String? okTitle;
|
||||
final String? cancelTitle;
|
||||
final double? minHeight;
|
||||
|
||||
const OkCancelButton(
|
||||
{Key? key,
|
||||
this.onOkPressed,
|
||||
this.onCancelPressed,
|
||||
this.okTitle,
|
||||
this.cancelTitle,
|
||||
this.minHeight})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (onOkPressed != null)
|
||||
PrimaryTextButton(okTitle ?? S.BTN_OK.toUpperCase(),
|
||||
onPressed: onOkPressed),
|
||||
HSpace(Insets.m),
|
||||
if (onCancelPressed != null)
|
||||
SecondaryTextButton(cancelTitle ?? S.BTN_CANCEL.toUpperCase(),
|
||||
onPressed: onCancelPressed),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../size.dart';
|
||||
import '../text_style.dart';
|
||||
import '../theme.dart';
|
||||
import 'base_styled_button.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
class PrimaryButton extends StatelessWidget {
|
||||
final Widget child;
|
||||
final VoidCallback? onPressed;
|
||||
final bool bigMode;
|
||||
|
||||
const PrimaryButton(
|
||||
{Key? key, required this.child, this.onPressed, this.bigMode = false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return BaseStyledButton(
|
||||
minWidth: bigMode ? 160 : 78,
|
||||
minHeight: bigMode ? 60 : 42,
|
||||
contentPadding: EdgeInsets.all(bigMode ? Insets.l : Insets.m),
|
||||
bgColor: theme.accent1Darker,
|
||||
hoverColor: theme.isDark ? theme.accent1 : theme.accent1Dark,
|
||||
downColor: theme.accent1Darker,
|
||||
borderRadius: bigMode ? Corners.s8 : Corners.s5,
|
||||
child: child,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PrimaryTextButton extends StatelessWidget {
|
||||
final String label;
|
||||
final VoidCallback? onPressed;
|
||||
final bool bigMode;
|
||||
|
||||
const PrimaryTextButton(this.label,
|
||||
{Key? key, this.onPressed, this.bigMode = false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextStyle txtStyle = (bigMode ? TextStyles.Callout : TextStyles.Footnote)
|
||||
.textColor(Colors.white);
|
||||
return PrimaryButton(
|
||||
bigMode: bigMode,
|
||||
onPressed: onPressed,
|
||||
child: Text(label, style: txtStyle));
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
import '../size.dart';
|
||||
import '../styled_image_icon.dart';
|
||||
import '../text_style.dart';
|
||||
import '../theme.dart';
|
||||
import 'base_styled_button.dart';
|
||||
|
||||
class SecondaryTextButton extends StatelessWidget {
|
||||
final String label;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const SecondaryTextButton(this.label, {Key? key, this.onPressed})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
TextStyle txtStyle = TextStyles.Footnote.textColor(theme.accent1Darker);
|
||||
return SecondaryButton(
|
||||
onPressed: onPressed, child: Text(label, style: txtStyle));
|
||||
}
|
||||
}
|
||||
|
||||
class SecondaryIconButton extends StatelessWidget {
|
||||
/// Must be either an `AssetImage` for an `ImageIcon` or an `IconData` for a regular `Icon`
|
||||
final AssetImage icon;
|
||||
final Function()? onPressed;
|
||||
final Color? color;
|
||||
|
||||
const SecondaryIconButton(this.icon, {Key? key, this.onPressed, this.color})
|
||||
: assert((icon is AssetImage) || (icon is IconData)),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return SecondaryButton(
|
||||
onPressed: onPressed,
|
||||
minHeight: 36,
|
||||
minWidth: 36,
|
||||
contentPadding: Insets.sm,
|
||||
child: StyledImageIcon(icon, size: 20, color: color ?? theme.grey),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondaryButton extends StatefulWidget {
|
||||
final Widget child;
|
||||
final VoidCallback? onPressed;
|
||||
final double? minWidth;
|
||||
final double? minHeight;
|
||||
final double? contentPadding;
|
||||
final Function(bool)? onFocusChanged;
|
||||
|
||||
const SecondaryButton(
|
||||
{Key? key,
|
||||
required this.child,
|
||||
this.onPressed,
|
||||
this.minWidth,
|
||||
this.minHeight,
|
||||
this.contentPadding,
|
||||
this.onFocusChanged})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_SecondaryButtonState createState() => _SecondaryButtonState();
|
||||
}
|
||||
|
||||
class _SecondaryButtonState extends State<SecondaryButton> {
|
||||
bool _isMouseOver = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return MouseRegion(
|
||||
onEnter: (_) => setState(() => _isMouseOver = true),
|
||||
onExit: (_) => setState(() => _isMouseOver = false),
|
||||
child: BaseStyledButton(
|
||||
minWidth: widget.minWidth ?? 78,
|
||||
minHeight: widget.minHeight ?? 42,
|
||||
contentPadding: EdgeInsets.all(widget.contentPadding ?? Insets.m),
|
||||
bgColor: theme.surface,
|
||||
outlineColor:
|
||||
(_isMouseOver ? theme.accent1 : theme.grey).withOpacity(.35),
|
||||
hoverColor: theme.surface,
|
||||
onFocusChanged: widget.onFocusChanged,
|
||||
downColor: theme.greyWeak.withOpacity(.35),
|
||||
borderRadius: Corners.s5,
|
||||
child: IgnorePointer(child: widget.child),
|
||||
onPressed: widget.onPressed,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
16
app_flowy/packages/flowy_style/lib/clickable_extension.dart
Normal file
16
app_flowy/packages/flowy_style/lib/clickable_extension.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
extension ClickableExtensions on Widget {
|
||||
Widget clickable(void Function() action, {bool opaque = true}) {
|
||||
return GestureDetector(
|
||||
behavior: opaque ? HitTestBehavior.opaque : HitTestBehavior.deferToChild,
|
||||
onTap: action,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
opaque: opaque,
|
||||
child: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
38
app_flowy/packages/flowy_style/lib/constraint_flex_view.dart
Normal file
38
app_flowy/packages/flowy_style/lib/constraint_flex_view.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ConstrainedFlexView extends StatelessWidget {
|
||||
final Widget child;
|
||||
final double minSize;
|
||||
final Axis axis;
|
||||
final EdgeInsets scrollPadding;
|
||||
|
||||
const ConstrainedFlexView(this.minSize,
|
||||
{Key? key,
|
||||
required this.child,
|
||||
this.axis = Axis.horizontal,
|
||||
this.scrollPadding = EdgeInsets.zero})
|
||||
: super(key: key);
|
||||
|
||||
bool get isHz => axis == Axis.horizontal;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
final viewSize = isHz ? constraints.maxWidth : constraints.maxHeight;
|
||||
if (viewSize > minSize) return child;
|
||||
return Padding(
|
||||
padding: scrollPadding,
|
||||
child: SingleChildScrollView(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: isHz ? double.infinity : minSize,
|
||||
maxWidth: isHz ? minSize : double.infinity),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class DialogContext extends Equatable {
|
||||
bool get barrierDismissable => true;
|
||||
final String identifier;
|
||||
|
||||
const DialogContext({required this.identifier});
|
||||
Widget buildWiget(BuildContext context);
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
class DialogSize {
|
||||
static double get minDialogWidth => 380;
|
||||
}
|
218
app_flowy/packages/flowy_style/lib/dialog/styled_dialogs.dart
Normal file
218
app_flowy/packages/flowy_style/lib/dialog/styled_dialogs.dart
Normal file
@ -0,0 +1,218 @@
|
||||
import 'package:flowy_style/buttons/ok_cancel_button.dart';
|
||||
import 'package:flowy_style/dialog/dialog_size.dart';
|
||||
import 'package:flowy_style/scrolling/styled_list.dart';
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flowy_style/spacing.dart';
|
||||
import 'package:flowy_style/text_style.dart';
|
||||
import 'package:flowy_style/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
import 'dialog_context.dart';
|
||||
export 'dialog_context.dart';
|
||||
|
||||
class Dialogs {
|
||||
static Future<dynamic> show(Widget child, BuildContext context) async {
|
||||
return await Navigator.of(context).push(
|
||||
StyledDialogRoute(
|
||||
pageBuilder: (BuildContext buildContext, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation) {
|
||||
return SafeArea(child: child);
|
||||
},
|
||||
),
|
||||
);
|
||||
/*return await showDialog(
|
||||
context: context ?? MainViewContext.value,
|
||||
builder: (context) => child,
|
||||
);*/
|
||||
}
|
||||
|
||||
static Future<dynamic> showWithContext(
|
||||
DialogContext dialogContext, BuildContext context) async {
|
||||
return await Navigator.of(context).push(
|
||||
StyledDialogRoute(
|
||||
barrierDismissible: dialogContext.barrierDismissable,
|
||||
pageBuilder: (BuildContext buildContext, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation) {
|
||||
return SafeArea(child: dialogContext.buildWiget(buildContext));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StyledDialogRoute<T> extends PopupRoute<T> {
|
||||
StyledDialogRoute({
|
||||
required RoutePageBuilder pageBuilder,
|
||||
bool barrierDismissible = false,
|
||||
String? barrierLabel,
|
||||
Color barrierColor = const Color(0x80000000),
|
||||
Duration transitionDuration = const Duration(milliseconds: 200),
|
||||
RouteTransitionsBuilder? transitionBuilder,
|
||||
RouteSettings? settings,
|
||||
}) : _pageBuilder = pageBuilder,
|
||||
_barrierDismissible = barrierDismissible,
|
||||
_barrierLabel = barrierLabel ?? '',
|
||||
_barrierColor = barrierColor,
|
||||
_transitionDuration = transitionDuration,
|
||||
_transitionBuilder = transitionBuilder,
|
||||
super(settings: settings);
|
||||
|
||||
final RoutePageBuilder _pageBuilder;
|
||||
|
||||
@override
|
||||
bool get barrierDismissible => _barrierDismissible;
|
||||
final bool _barrierDismissible;
|
||||
|
||||
@override
|
||||
String get barrierLabel => _barrierLabel;
|
||||
final String _barrierLabel;
|
||||
|
||||
@override
|
||||
Color get barrierColor => _barrierColor;
|
||||
final Color _barrierColor;
|
||||
|
||||
@override
|
||||
Duration get transitionDuration => _transitionDuration;
|
||||
final Duration _transitionDuration;
|
||||
|
||||
final RouteTransitionsBuilder? _transitionBuilder;
|
||||
|
||||
@override
|
||||
Widget buildPage(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation) {
|
||||
return Semantics(
|
||||
child: _pageBuilder(context, animation, secondaryAnimation),
|
||||
scopesRoute: true,
|
||||
explicitChildNodes: true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTransitions(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation, Widget child) {
|
||||
if (_transitionBuilder == null) {
|
||||
return FadeTransition(
|
||||
opacity: CurvedAnimation(parent: animation, curve: Curves.linear),
|
||||
child: child);
|
||||
} else {
|
||||
return _transitionBuilder!(context, animation, secondaryAnimation, child);
|
||||
} // Some default transition
|
||||
}
|
||||
}
|
||||
|
||||
class StyledDialog extends StatelessWidget {
|
||||
final Widget child;
|
||||
final double? maxWidth;
|
||||
final double? maxHeight;
|
||||
final EdgeInsets? padding;
|
||||
final EdgeInsets? margin;
|
||||
final BorderRadius? borderRadius;
|
||||
final Color? bgColor;
|
||||
final bool shrinkWrap;
|
||||
|
||||
const StyledDialog({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.maxWidth,
|
||||
this.maxHeight,
|
||||
this.padding,
|
||||
this.margin,
|
||||
this.bgColor,
|
||||
this.borderRadius,
|
||||
this.shrinkWrap = true,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final radius = borderRadius ?? Corners.s8Border;
|
||||
final theme = context.watch<AppTheme>();
|
||||
|
||||
Widget innerContent = Container(
|
||||
padding: padding ?? EdgeInsets.all(Insets.lGutter),
|
||||
color: bgColor ?? theme.surface,
|
||||
child: child,
|
||||
);
|
||||
|
||||
if (shrinkWrap) {
|
||||
innerContent =
|
||||
IntrinsicWidth(child: IntrinsicHeight(child: innerContent));
|
||||
}
|
||||
|
||||
return FocusTraversalGroup(
|
||||
child: Container(
|
||||
margin: margin ?? EdgeInsets.all(Insets.lGutter * 2),
|
||||
alignment: Alignment.center,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: DialogSize.minDialogWidth,
|
||||
maxHeight: maxHeight ?? double.infinity,
|
||||
maxWidth: maxWidth ?? double.infinity,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: SingleChildScrollView(
|
||||
physics: StyledScrollPhysics(),
|
||||
//https://medium.com/saugo360/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: innerContent,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class OkCancelDialog extends StatelessWidget {
|
||||
final VoidCallback? onOkPressed;
|
||||
final VoidCallback? onCancelPressed;
|
||||
final String? okTitle;
|
||||
final String? cancelTitle;
|
||||
final String? title;
|
||||
final String message;
|
||||
final double? maxWidth;
|
||||
|
||||
const OkCancelDialog(
|
||||
{Key? key,
|
||||
this.onOkPressed,
|
||||
this.onCancelPressed,
|
||||
this.okTitle,
|
||||
this.cancelTitle,
|
||||
this.title,
|
||||
required this.message,
|
||||
this.maxWidth})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return StyledDialog(
|
||||
maxWidth: maxWidth ?? 500,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (title != null) ...[
|
||||
Text(title!.toUpperCase(),
|
||||
style: TextStyles.T1.textColor(theme.accent1Darker)),
|
||||
VSpace(Insets.sm * 1.5),
|
||||
Container(color: theme.greyWeak.withOpacity(.35), height: 1),
|
||||
VSpace(Insets.m * 1.5),
|
||||
],
|
||||
Text(message, style: TextStyles.Body1.textHeight(1.5)),
|
||||
SizedBox(height: Insets.l),
|
||||
OkCancelButton(
|
||||
onOkPressed: onOkPressed,
|
||||
onCancelPressed: onCancelPressed,
|
||||
okTitle: okTitle?.toUpperCase(),
|
||||
cancelTitle: cancelTitle?.toUpperCase(),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
35
app_flowy/packages/flowy_style/lib/mouse_hover_builder.dart
Normal file
35
app_flowy/packages/flowy_style/lib/mouse_hover_builder.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool isHovering);
|
||||
|
||||
class MouseHoverBuilder extends StatefulWidget {
|
||||
final bool isClickable;
|
||||
|
||||
const MouseHoverBuilder(
|
||||
{Key? key, required this.builder, this.isClickable = false})
|
||||
: super(key: key);
|
||||
|
||||
final HoverBuilder builder;
|
||||
|
||||
@override
|
||||
_MouseHoverBuilderState createState() => _MouseHoverBuilderState();
|
||||
}
|
||||
|
||||
class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
|
||||
bool isOver = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: widget.isClickable
|
||||
? SystemMouseCursors.click
|
||||
: SystemMouseCursors.basic,
|
||||
onEnter: (p) => setOver(true),
|
||||
onExit: (p) => setOver(false),
|
||||
child: widget.builder(context, isOver),
|
||||
);
|
||||
}
|
||||
|
||||
void setOver(bool value) => setState(() => isOver = value);
|
||||
}
|
33
app_flowy/packages/flowy_style/lib/rounded_button.dart
Normal file
33
app_flowy/packages/flowy_style/lib/rounded_button.dart
Normal file
@ -0,0 +1,33 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RoundedButton extends StatelessWidget {
|
||||
final VoidCallback? press;
|
||||
final String? title;
|
||||
final Size? size;
|
||||
|
||||
const RoundedButton({
|
||||
Key? key,
|
||||
this.press,
|
||||
this.title,
|
||||
this.size,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: 100,
|
||||
maxWidth: size?.width ?? double.infinity,
|
||||
minHeight: 50,
|
||||
maxHeight: size?.height ?? double.infinity,
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextButton(
|
||||
child: Text(title ?? ''),
|
||||
onPressed: press,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
35
app_flowy/packages/flowy_style/lib/rounded_input_field.dart
Normal file
35
app_flowy/packages/flowy_style/lib/rounded_input_field.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flowy_style/text_field_container.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RoundedInputField extends StatelessWidget {
|
||||
final String? hintText;
|
||||
final IconData? icon;
|
||||
final bool obscureText;
|
||||
final ValueChanged<String>? onChanged;
|
||||
|
||||
const RoundedInputField({
|
||||
Key? key,
|
||||
this.hintText,
|
||||
this.icon = Icons.person,
|
||||
this.obscureText = false,
|
||||
this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFieldContainer(
|
||||
child: TextFormField(
|
||||
onChanged: onChanged,
|
||||
cursorColor: const Color(0xFF6F35A5),
|
||||
obscureText: obscureText,
|
||||
decoration: InputDecoration(
|
||||
icon: Icon(
|
||||
icon,
|
||||
color: const Color(0xFF6F35A5),
|
||||
),
|
||||
hintText: hintText,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'styled_scroll_bar.dart';
|
||||
|
||||
class StyledScrollPhysics extends AlwaysScrollableScrollPhysics {}
|
||||
|
||||
/// Core ListView for the app.
|
||||
/// Wraps a [ScrollbarListStack] + [ListView.builder] and assigns the 'Styled' scroll physics for the app
|
||||
/// Exposes a controller so other widgets can manipulate the list
|
||||
class StyledListView extends StatefulWidget {
|
||||
final double? itemExtent;
|
||||
final int? itemCount;
|
||||
final Axis axis;
|
||||
final EdgeInsets? padding;
|
||||
final EdgeInsets? scrollbarPadding;
|
||||
final double? barSize;
|
||||
|
||||
final IndexedWidgetBuilder itemBuilder;
|
||||
|
||||
StyledListView({
|
||||
Key? key,
|
||||
required this.itemBuilder,
|
||||
required this.itemCount,
|
||||
this.itemExtent,
|
||||
this.axis = Axis.vertical,
|
||||
this.padding,
|
||||
this.barSize,
|
||||
this.scrollbarPadding,
|
||||
}) : super(key: key) {
|
||||
assert(itemExtent != 0, 'Item extent should never be 0, null is ok.');
|
||||
}
|
||||
|
||||
@override
|
||||
StyledListViewState createState() => StyledListViewState();
|
||||
}
|
||||
|
||||
/// State is public so this can easily be controlled externally
|
||||
class StyledListViewState extends State<StyledListView> {
|
||||
late ScrollController scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scrollController = ScrollController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(StyledListView oldWidget) {
|
||||
if (oldWidget.itemCount != widget.itemCount ||
|
||||
oldWidget.itemExtent != widget.itemExtent) {
|
||||
setState(() {});
|
||||
}
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final contentSize = (widget.itemCount ?? 0.0) * (widget.itemExtent ?? 00.0);
|
||||
Widget listContent = ScrollbarListStack(
|
||||
contentSize: contentSize,
|
||||
axis: widget.axis,
|
||||
controller: scrollController,
|
||||
barSize: widget.barSize ?? 12,
|
||||
scrollbarPadding: widget.scrollbarPadding,
|
||||
child: ListView.builder(
|
||||
padding: widget.padding,
|
||||
scrollDirection: widget.axis,
|
||||
physics: StyledScrollPhysics(),
|
||||
controller: scrollController,
|
||||
itemExtent: widget.itemExtent,
|
||||
itemCount: widget.itemCount,
|
||||
itemBuilder: (c, i) => widget.itemBuilder(c, i),
|
||||
),
|
||||
);
|
||||
return listContent;
|
||||
}
|
||||
}
|
@ -0,0 +1,243 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flowy_style/mouse_hover_builder.dart';
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flowy_style/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class StyledScrollbar extends StatefulWidget {
|
||||
final double? size;
|
||||
final Axis axis;
|
||||
final ScrollController controller;
|
||||
final Function(double)? onDrag;
|
||||
final bool showTrack;
|
||||
final Color? handleColor;
|
||||
final Color? trackColor;
|
||||
|
||||
// ignore: todo
|
||||
// TODO: Remove contentHeight if we can fix this issue
|
||||
// https://stackoverflow.com/questions/60855712/flutter-how-to-force-scrollcontroller-to-recalculate-position-maxextents
|
||||
final double? contentSize;
|
||||
|
||||
const StyledScrollbar(
|
||||
{Key? key,
|
||||
this.size,
|
||||
required this.axis,
|
||||
required this.controller,
|
||||
this.onDrag,
|
||||
this.contentSize,
|
||||
this.showTrack = false,
|
||||
this.handleColor,
|
||||
this.trackColor})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
ScrollbarState createState() => ScrollbarState();
|
||||
}
|
||||
|
||||
class ScrollbarState extends State<StyledScrollbar> {
|
||||
double _viewExtent = 100;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
widget.controller.addListener(() => setState(() {}));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(StyledScrollbar oldWidget) {
|
||||
if (oldWidget.contentSize != widget.contentSize) setState(() {});
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
// void calculateSize() {
|
||||
// //[SB] Only hack I can find to make the ScrollController update it's maxExtents.
|
||||
// //Call this whenever the content changes, so the scrollbar can recalculate it's size
|
||||
// widget.controller.jumpTo(widget.controller.position.pixels + 1);
|
||||
// Future.microtask(() => widget.controller
|
||||
// .animateTo(widget.controller.position.pixels - 1, duration: 100.milliseconds, curve: Curves.linear));
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return LayoutBuilder(
|
||||
builder: (_, BoxConstraints constraints) {
|
||||
double maxExtent;
|
||||
final contentSize = widget.contentSize;
|
||||
switch (widget.axis) {
|
||||
case Axis.vertical:
|
||||
// Use supplied contentSize if we have it, otherwise just fallback to maxScrollExtents
|
||||
if (contentSize != null && contentSize > 0) {
|
||||
maxExtent = contentSize - constraints.maxHeight;
|
||||
} else {
|
||||
maxExtent = widget.controller.position.maxScrollExtent;
|
||||
}
|
||||
|
||||
_viewExtent = constraints.maxHeight;
|
||||
|
||||
break;
|
||||
case Axis.horizontal:
|
||||
// Use supplied contentSize if we have it, otherwise just fallback to maxScrollExtents
|
||||
|
||||
if (contentSize != null && contentSize > 0) {
|
||||
maxExtent = contentSize - constraints.maxWidth;
|
||||
} else {
|
||||
maxExtent = widget.controller.position.maxScrollExtent;
|
||||
}
|
||||
_viewExtent = constraints.maxWidth;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
final contentExtent = maxExtent + _viewExtent;
|
||||
// Calculate the alignment for the handle, this is a value between 0 and 1,
|
||||
// it automatically takes the handle size into acct
|
||||
// ignore: omit_local_variable_types
|
||||
double handleAlignment =
|
||||
maxExtent == 0 ? 0 : widget.controller.offset / maxExtent;
|
||||
|
||||
// Convert handle alignment from [0, 1] to [-1, 1]
|
||||
handleAlignment *= 2.0;
|
||||
handleAlignment -= 1.0;
|
||||
|
||||
// Calculate handleSize by comparing the total content size to our viewport
|
||||
var handleExtent = _viewExtent;
|
||||
if (contentExtent > _viewExtent) {
|
||||
//Make sure handle is never small than the minSize
|
||||
handleExtent = max(60, _viewExtent * _viewExtent / contentExtent);
|
||||
}
|
||||
// Hide the handle if content is < the viewExtent
|
||||
var showHandle = contentExtent > _viewExtent && contentExtent > 0;
|
||||
// Handle color
|
||||
var handleColor = widget.handleColor ??
|
||||
(theme.isDark ? theme.greyWeak.withOpacity(.2) : theme.greyWeak);
|
||||
// Track color
|
||||
var trackColor = widget.trackColor ??
|
||||
(theme.isDark
|
||||
? theme.greyWeak.withOpacity(.1)
|
||||
: theme.greyWeak.withOpacity(.3));
|
||||
|
||||
//Layout the stack, it just contains a child, and
|
||||
return Stack(children: <Widget>[
|
||||
/// TRACK, thin strip, aligned along the end of the parent
|
||||
if (widget.showTrack)
|
||||
Align(
|
||||
alignment: const Alignment(1, 1),
|
||||
child: Container(
|
||||
color: trackColor,
|
||||
width: widget.axis == Axis.vertical
|
||||
? widget.size
|
||||
: double.infinity,
|
||||
height: widget.axis == Axis.horizontal
|
||||
? widget.size
|
||||
: double.infinity,
|
||||
),
|
||||
),
|
||||
|
||||
/// HANDLE - Clickable shape that changes scrollController when dragged
|
||||
Align(
|
||||
// Use calculated alignment to position handle from -1 to 1, let Alignment do the rest of the work
|
||||
alignment: Alignment(
|
||||
widget.axis == Axis.vertical ? 1 : handleAlignment,
|
||||
widget.axis == Axis.horizontal ? 1 : handleAlignment,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onVerticalDragUpdate: _handleVerticalDrag,
|
||||
onHorizontalDragUpdate: _handleHorizontalDrag,
|
||||
// HANDLE SHAPE
|
||||
child: MouseHoverBuilder(
|
||||
builder: (_, isHovered) => Container(
|
||||
width:
|
||||
widget.axis == Axis.vertical ? widget.size : handleExtent,
|
||||
height: widget.axis == Axis.horizontal
|
||||
? widget.size
|
||||
: handleExtent,
|
||||
decoration: BoxDecoration(
|
||||
color: handleColor.withOpacity(isHovered ? 1 : .85),
|
||||
borderRadius: Corners.s3Border),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
]).opacity(showHandle ? 1.0 : 0.0, animate: false);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _handleHorizontalDrag(DragUpdateDetails details) {
|
||||
var pos = widget.controller.offset;
|
||||
var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) /
|
||||
_viewExtent;
|
||||
widget.controller.jumpTo((pos + details.delta.dx * pxRatio)
|
||||
.clamp(0.0, widget.controller.position.maxScrollExtent));
|
||||
widget.onDrag?.call(details.delta.dx);
|
||||
}
|
||||
|
||||
void _handleVerticalDrag(DragUpdateDetails details) {
|
||||
var pos = widget.controller.offset;
|
||||
var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) /
|
||||
_viewExtent;
|
||||
widget.controller.jumpTo((pos + details.delta.dy * pxRatio)
|
||||
.clamp(0.0, widget.controller.position.maxScrollExtent));
|
||||
widget.onDrag?.call(details.delta.dy);
|
||||
}
|
||||
}
|
||||
|
||||
class ScrollbarListStack extends StatelessWidget {
|
||||
final double barSize;
|
||||
final Axis axis;
|
||||
final Widget child;
|
||||
final ScrollController controller;
|
||||
final double? contentSize;
|
||||
final EdgeInsets? scrollbarPadding;
|
||||
final Color? handleColor;
|
||||
final Color? trackColor;
|
||||
|
||||
const ScrollbarListStack(
|
||||
{Key? key,
|
||||
required this.barSize,
|
||||
required this.axis,
|
||||
required this.child,
|
||||
required this.controller,
|
||||
this.contentSize,
|
||||
this.scrollbarPadding,
|
||||
this.handleColor,
|
||||
this.trackColor})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
/// LIST
|
||||
/// Wrap with a bit of padding on the right
|
||||
child.padding(
|
||||
right: axis == Axis.vertical ? barSize + Insets.sm : 0,
|
||||
bottom: axis == Axis.horizontal ? barSize + Insets.sm : 0,
|
||||
),
|
||||
|
||||
/// SCROLLBAR
|
||||
Padding(
|
||||
padding: scrollbarPadding ?? EdgeInsets.zero,
|
||||
child: StyledScrollbar(
|
||||
size: barSize,
|
||||
axis: axis,
|
||||
controller: controller,
|
||||
contentSize: contentSize,
|
||||
trackColor: trackColor,
|
||||
handleColor: handleColor,
|
||||
showTrack: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'styled_list.dart';
|
||||
import 'styled_scroll_bar.dart';
|
||||
|
||||
class StyledSingleChildScrollView extends StatefulWidget {
|
||||
final double? contentSize;
|
||||
final Axis axis;
|
||||
final Color? trackColor;
|
||||
final Color? handleColor;
|
||||
final ScrollController? controller;
|
||||
|
||||
final Widget? child;
|
||||
|
||||
const StyledSingleChildScrollView({
|
||||
Key? key,
|
||||
@required this.child,
|
||||
this.contentSize,
|
||||
this.axis = Axis.vertical,
|
||||
this.trackColor,
|
||||
this.handleColor,
|
||||
this.controller,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_StyledSingleChildScrollViewState createState() =>
|
||||
_StyledSingleChildScrollViewState();
|
||||
}
|
||||
|
||||
class _StyledSingleChildScrollViewState
|
||||
extends State<StyledSingleChildScrollView> {
|
||||
late ScrollController scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scrollController = widget.controller ?? ScrollController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(StyledSingleChildScrollView oldWidget) {
|
||||
if (oldWidget.child != widget.child) {
|
||||
setState(() {});
|
||||
}
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScrollbarListStack(
|
||||
contentSize: widget.contentSize,
|
||||
axis: widget.axis,
|
||||
controller: scrollController,
|
||||
barSize: 12,
|
||||
trackColor: widget.trackColor,
|
||||
handleColor: widget.handleColor,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: widget.axis,
|
||||
physics: StyledScrollPhysics(),
|
||||
controller: scrollController,
|
||||
child: widget.child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StyledCustomScrollView extends StatefulWidget {
|
||||
final double? contentSize;
|
||||
final Axis axis;
|
||||
final Color? trackColor;
|
||||
final Color? handleColor;
|
||||
final ScrollController? controller;
|
||||
final List<Widget> slivers;
|
||||
|
||||
const StyledCustomScrollView({
|
||||
Key? key,
|
||||
this.contentSize,
|
||||
this.axis = Axis.vertical,
|
||||
this.trackColor,
|
||||
this.handleColor,
|
||||
this.controller,
|
||||
this.slivers = const <Widget>[],
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_StyledCustomScrollViewState createState() => _StyledCustomScrollViewState();
|
||||
}
|
||||
|
||||
class _StyledCustomScrollViewState extends State<StyledCustomScrollView> {
|
||||
late ScrollController scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scrollController = widget.controller ?? ScrollController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(StyledCustomScrollView oldWidget) {
|
||||
if (oldWidget.slivers != widget.slivers) {
|
||||
setState(() {});
|
||||
}
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScrollbarListStack(
|
||||
contentSize: widget.contentSize,
|
||||
axis: widget.axis,
|
||||
controller: scrollController,
|
||||
barSize: 12,
|
||||
trackColor: widget.trackColor,
|
||||
handleColor: widget.handleColor,
|
||||
child: CustomScrollView(
|
||||
scrollDirection: widget.axis,
|
||||
physics: StyledScrollPhysics(),
|
||||
controller: scrollController,
|
||||
slivers: widget.slivers,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
43
app_flowy/packages/flowy_style/lib/seperated_column.dart
Normal file
43
app_flowy/packages/flowy_style/lib/seperated_column.dart
Normal file
@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef SeparatorBuilder = Widget Function();
|
||||
|
||||
class SeparatedColumn extends StatelessWidget {
|
||||
final List<Widget> children;
|
||||
final SeparatorBuilder? separatorBuilder;
|
||||
final MainAxisAlignment mainAxisAlignment;
|
||||
final CrossAxisAlignment crossAxisAlignment;
|
||||
final MainAxisSize mainAxisSize;
|
||||
final TextBaseline? textBaseline;
|
||||
final TextDirection? textDirection;
|
||||
final VerticalDirection verticalDirection;
|
||||
|
||||
const SeparatedColumn({
|
||||
Key? key,
|
||||
required this.children,
|
||||
this.separatorBuilder,
|
||||
this.mainAxisAlignment = MainAxisAlignment.start,
|
||||
this.crossAxisAlignment = CrossAxisAlignment.center,
|
||||
this.mainAxisSize = MainAxisSize.max,
|
||||
this.verticalDirection = VerticalDirection.down,
|
||||
this.textBaseline,
|
||||
this.textDirection,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var c = children.toList();
|
||||
for (var i = c.length; i-- > 0;) {
|
||||
if (i > 0 && separatorBuilder != null) c.insert(i, separatorBuilder!());
|
||||
}
|
||||
return Column(
|
||||
children: c,
|
||||
mainAxisAlignment: mainAxisAlignment,
|
||||
crossAxisAlignment: crossAxisAlignment,
|
||||
mainAxisSize: mainAxisSize,
|
||||
textBaseline: textBaseline,
|
||||
textDirection: textDirection,
|
||||
verticalDirection: verticalDirection,
|
||||
);
|
||||
}
|
||||
}
|
94
app_flowy/packages/flowy_style/lib/size.dart
Normal file
94
app_flowy/packages/flowy_style/lib/size.dart
Normal file
@ -0,0 +1,94 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PageBreaks {
|
||||
static double get largePhone => 550;
|
||||
|
||||
static double get tabletPortrait => 768;
|
||||
|
||||
static double get tabletLandscape => 1024;
|
||||
|
||||
static double get desktop => 1440;
|
||||
}
|
||||
|
||||
class Insets {
|
||||
static double gutterScale = 1;
|
||||
|
||||
static double scale = 1;
|
||||
|
||||
/// Dynamic insets, may get scaled with the device size
|
||||
static double get mGutter => m * gutterScale;
|
||||
|
||||
static double get lGutter => l * gutterScale;
|
||||
|
||||
static double get xs => 2 * scale;
|
||||
|
||||
static double get sm => 6 * scale;
|
||||
|
||||
static double get m => 12 * scale;
|
||||
|
||||
static double get l => 24 * scale;
|
||||
|
||||
static double get xl => 36 * scale;
|
||||
}
|
||||
|
||||
class FontSizes {
|
||||
static double get scale => 1;
|
||||
|
||||
static double get s11 => 11 * scale;
|
||||
|
||||
static double get s12 => 12 * scale;
|
||||
|
||||
static double get s14 => 14 * scale;
|
||||
|
||||
static double get s16 => 16 * scale;
|
||||
|
||||
static double get s18 => 18 * scale;
|
||||
}
|
||||
|
||||
class Sizes {
|
||||
static double hitScale = 1;
|
||||
|
||||
static double get hit => 40 * hitScale;
|
||||
|
||||
static double get iconMed => 20;
|
||||
|
||||
static double get sideBarSm => 200 * hitScale;
|
||||
|
||||
static double get sideBarMed => 220 * hitScale;
|
||||
|
||||
static double get sideBarLg => 290 * hitScale;
|
||||
}
|
||||
|
||||
class Corners {
|
||||
static double get btn => s5;
|
||||
|
||||
static double get dialog => 12;
|
||||
|
||||
/// Xs
|
||||
static double get s3 => 3;
|
||||
|
||||
static BorderRadius get s3Border => BorderRadius.all(s3Radius);
|
||||
|
||||
static Radius get s3Radius => Radius.circular(s3);
|
||||
|
||||
/// Small
|
||||
static double get s5 => 5;
|
||||
|
||||
static BorderRadius get s5Border => BorderRadius.all(s5Radius);
|
||||
|
||||
static Radius get s5Radius => Radius.circular(s5);
|
||||
|
||||
/// Medium
|
||||
static double get s8 => 8;
|
||||
|
||||
static BorderRadius get s8Border => BorderRadius.all(s8Radius);
|
||||
|
||||
static Radius get s8Radius => Radius.circular(s8);
|
||||
|
||||
/// Large
|
||||
static double get s10 => 10;
|
||||
|
||||
static BorderRadius get s10Border => BorderRadius.all(s10Radius);
|
||||
|
||||
static Radius get s10Radius => Radius.circular(s10);
|
||||
}
|
29
app_flowy/packages/flowy_style/lib/spacing.dart
Normal file
29
app_flowy/packages/flowy_style/lib/spacing.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class Space extends StatelessWidget {
|
||||
final double width;
|
||||
final double height;
|
||||
|
||||
const Space(this.width, this.height, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SizedBox(width: width, height: height);
|
||||
}
|
||||
|
||||
class VSpace extends StatelessWidget {
|
||||
final double size;
|
||||
|
||||
const VSpace(this.size, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Space(0, size);
|
||||
}
|
||||
|
||||
class HSpace extends StatelessWidget {
|
||||
final double size;
|
||||
|
||||
const HSpace(this.size, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Space(size, 0);
|
||||
}
|
60
app_flowy/packages/flowy_style/lib/strings.dart
Normal file
60
app_flowy/packages/flowy_style/lib/strings.dart
Normal file
@ -0,0 +1,60 @@
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
class _Strings {
|
||||
static _Strings instance = _Strings();
|
||||
|
||||
String TITLE_CONTACTS_PAGE = "Contacts";
|
||||
String TITLE_WHATS_HAPPENING = "What's happening this week?";
|
||||
String TITLE_ADD_CONTACT = "Add Contact";
|
||||
String TITLE_EDIT_CONTACT = "Edit Contact";
|
||||
|
||||
String BTN_OK = "Ok";
|
||||
String BTN_CANCEL = "Cancel";
|
||||
String BTN_SIGN_IN = "Sign In";
|
||||
String BTN_SIGN_OUT = "Sign Out";
|
||||
String BTN_COMPLETE = "Complete";
|
||||
String BTN_SAVE = "Save";
|
||||
|
||||
String LBL_WELCOME = "Welcome!";
|
||||
String LBL_NAME_FIRST = "First Name";
|
||||
String LBL_NAME_MIDDLE = "Middle Name";
|
||||
String LBL_NAME_LAST = "Last Name";
|
||||
String LBL_STEP_X = "Step {0}";
|
||||
|
||||
String ERR_DEVICE_OAUTH_FAILED_TITLE = "Unable to connect to your account.";
|
||||
String ERR_DEVICE_OAUTH_FAILED_MSG =
|
||||
"Please make sure you've completed the sign-in process in your browser.";
|
||||
|
||||
String GOOGLE_OAUTH_TITLE = "GOOGLE SIGN-IN";
|
||||
String GOOGLE_OAUTH_INSTRUCTIONS_1 =
|
||||
"In order to import your Google Contacts, you'll need to authorize this application using your web browser.";
|
||||
String GOOGLE_OAUTH_INSTRUCTIONS_2 =
|
||||
"Copy this code to your clipboard by clicking the icon or selecting the text:";
|
||||
String GOOGLE_OAUTH_INSTRUCTIONS_3 =
|
||||
"Navigate to the following link in your web browser, and enter the above code:";
|
||||
String GOOGLE_OAUTH_INSTRUCTIONS_4 =
|
||||
"Press the button below when you've completed signup:";
|
||||
}
|
||||
|
||||
_Strings get S => _Strings.instance;
|
||||
|
||||
extension AddSupplant on String {
|
||||
String sup(
|
||||
[dynamic v0,
|
||||
dynamic v1,
|
||||
dynamic v2,
|
||||
dynamic v3,
|
||||
dynamic v4,
|
||||
dynamic v5,
|
||||
dynamic v6]) {
|
||||
var _s = this;
|
||||
if (v0 != null) _s = _s.replaceAll("{0}", "$v0");
|
||||
if (v1 != null) _s = _s.replaceAll("{1}", "$v1");
|
||||
if (v2 != null) _s = _s.replaceAll("{2}", "$v2");
|
||||
if (v3 != null) _s = _s.replaceAll("{3}", "$v3");
|
||||
if (v4 != null) _s = _s.replaceAll("{4}", "$v4");
|
||||
if (v5 != null) _s = _s.replaceAll("{5}", "$v5");
|
||||
if (v6 != null) _s = _s.replaceAll("{6}", "$v6");
|
||||
return _s;
|
||||
}
|
||||
}
|
18
app_flowy/packages/flowy_style/lib/styled_bar_title.dart
Normal file
18
app_flowy/packages/flowy_style/lib/styled_bar_title.dart
Normal file
@ -0,0 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyleBarTitle extends StatelessWidget {
|
||||
final String title;
|
||||
|
||||
const StyleBarTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
style: const TextStyle(fontSize: 24),
|
||||
);
|
||||
}
|
||||
}
|
15
app_flowy/packages/flowy_style/lib/styled_close_button.dart
Normal file
15
app_flowy/packages/flowy_style/lib/styled_close_button.dart
Normal file
@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyleCloseButton extends StatelessWidget {
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const StyleCloseButton({
|
||||
Key? key,
|
||||
this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(onPressed: onPressed, child: const Icon(Icons.close));
|
||||
}
|
||||
}
|
44
app_flowy/packages/flowy_style/lib/styled_container.dart
Normal file
44
app_flowy/packages/flowy_style/lib/styled_container.dart
Normal file
@ -0,0 +1,44 @@
|
||||
import 'package:flowy_style/time/duration.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyledContainer extends StatelessWidget {
|
||||
final Color color;
|
||||
final BorderRadiusGeometry? borderRadius;
|
||||
final List<BoxShadow>? shadows;
|
||||
final Widget? child;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final Alignment? align;
|
||||
final EdgeInsets? margin;
|
||||
final Duration? duration;
|
||||
final BoxBorder? border;
|
||||
|
||||
const StyledContainer(this.color,
|
||||
{Key? key,
|
||||
this.borderRadius,
|
||||
this.shadows,
|
||||
this.child,
|
||||
this.width,
|
||||
this.height,
|
||||
this.align,
|
||||
this.margin,
|
||||
this.duration,
|
||||
this.border})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
width: width,
|
||||
height: height,
|
||||
child: child,
|
||||
margin: margin,
|
||||
alignment: align,
|
||||
duration: duration ?? Durations.medium,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: borderRadius,
|
||||
boxShadow: shadows,
|
||||
border: border));
|
||||
}
|
||||
}
|
17
app_flowy/packages/flowy_style/lib/styled_image_icon.dart
Normal file
17
app_flowy/packages/flowy_style/lib/styled_image_icon.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyledImageIcon extends StatelessWidget {
|
||||
final AssetImage image;
|
||||
final Color? color;
|
||||
final double? size;
|
||||
|
||||
const StyledImageIcon(this.image, {Key? key, this.color, this.size})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ImageIcon(image,
|
||||
size: size ?? Sizes.iconMed, color: color ?? Colors.white);
|
||||
}
|
||||
}
|
354
app_flowy/packages/flowy_style/lib/styled_text_input.dart
Normal file
354
app_flowy/packages/flowy_style/lib/styled_text_input.dart
Normal file
@ -0,0 +1,354 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
import 'package:flowy_style/size.dart';
|
||||
import 'package:flowy_style/text_style.dart';
|
||||
import 'package:flowy_style/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
class StyledFormTextInput extends StatelessWidget {
|
||||
static EdgeInsets kDefaultTextInputPadding =
|
||||
EdgeInsets.only(bottom: Insets.sm, top: 4);
|
||||
|
||||
final String? label;
|
||||
final bool? autoFocus;
|
||||
final String? initialValue;
|
||||
final String? hintText;
|
||||
final EdgeInsets? contentPadding;
|
||||
final TextStyle? textStyle;
|
||||
final int? maxLines;
|
||||
final TextEditingController? controller;
|
||||
final TextCapitalization? capitalization;
|
||||
final Function(String)? onChanged;
|
||||
final Function()? onEditingComplete;
|
||||
final Function(bool)? onFocusChanged;
|
||||
final Function(FocusNode)? onFocusCreated;
|
||||
|
||||
const StyledFormTextInput(
|
||||
{Key? key,
|
||||
this.label,
|
||||
this.autoFocus,
|
||||
this.initialValue,
|
||||
this.onChanged,
|
||||
this.onEditingComplete,
|
||||
this.hintText,
|
||||
this.onFocusChanged,
|
||||
this.onFocusCreated,
|
||||
this.controller,
|
||||
this.contentPadding,
|
||||
this.capitalization,
|
||||
this.textStyle,
|
||||
this.maxLines})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StyledSearchTextInput(
|
||||
capitalization: capitalization,
|
||||
label: label,
|
||||
autoFocus: autoFocus,
|
||||
initialValue: initialValue,
|
||||
onChanged: onChanged,
|
||||
onFocusCreated: onFocusCreated,
|
||||
style: textStyle ?? TextStyles.Body1,
|
||||
onEditingComplete: onEditingComplete,
|
||||
onFocusChanged: onFocusChanged,
|
||||
controller: controller,
|
||||
maxLines: maxLines,
|
||||
inputDecoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: contentPadding ?? kDefaultTextInputPadding,
|
||||
border: const ThinUnderlineBorder(
|
||||
borderSide: BorderSide(width: 5, color: Colors.red)),
|
||||
//focusedBorder: UnderlineInputBorder(borderSide: BorderSide(width: .5, color: Colors.red)),
|
||||
hintText: hintText,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StyledSearchTextInput extends StatefulWidget {
|
||||
final String? label;
|
||||
final TextStyle? style;
|
||||
final EdgeInsets? contentPadding;
|
||||
final bool? autoFocus;
|
||||
final bool? obscureText;
|
||||
final IconData? icon;
|
||||
final String? initialValue;
|
||||
final int? maxLines;
|
||||
final TextEditingController? controller;
|
||||
final TextCapitalization? capitalization;
|
||||
final TextInputType? type;
|
||||
final bool? enabled;
|
||||
final bool? autoValidate;
|
||||
final bool? enableSuggestions;
|
||||
final bool? autoCorrect;
|
||||
final String? errorText;
|
||||
final String? hintText;
|
||||
final Widget? prefixIcon;
|
||||
final Widget? suffixIcon;
|
||||
final InputDecoration? inputDecoration;
|
||||
|
||||
final Function(String)? onChanged;
|
||||
final Function()? onEditingComplete;
|
||||
final Function()? onEditingCancel;
|
||||
final Function(bool)? onFocusChanged;
|
||||
final Function(FocusNode)? onFocusCreated;
|
||||
final Function(String)? onFieldSubmitted;
|
||||
final Function(String?)? onSaved;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
const StyledSearchTextInput({
|
||||
Key? key,
|
||||
this.label,
|
||||
this.autoFocus = false,
|
||||
this.obscureText = false,
|
||||
this.type = TextInputType.text,
|
||||
this.icon,
|
||||
this.initialValue = '',
|
||||
this.controller,
|
||||
this.enabled,
|
||||
this.autoValidate = false,
|
||||
this.enableSuggestions = true,
|
||||
this.autoCorrect = true,
|
||||
this.errorText,
|
||||
this.style,
|
||||
this.contentPadding,
|
||||
this.prefixIcon,
|
||||
this.suffixIcon,
|
||||
this.inputDecoration,
|
||||
this.onChanged,
|
||||
this.onEditingComplete,
|
||||
this.onEditingCancel,
|
||||
this.onFocusChanged,
|
||||
this.onFocusCreated,
|
||||
this.onFieldSubmitted,
|
||||
this.onSaved,
|
||||
this.onTap,
|
||||
this.hintText,
|
||||
this.capitalization,
|
||||
this.maxLines,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
StyledSearchTextInputState createState() => StyledSearchTextInputState();
|
||||
}
|
||||
|
||||
class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
||||
late TextEditingController _controller;
|
||||
late FocusNode _focusNode;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller =
|
||||
widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
_focusNode = FocusNode(
|
||||
debugLabel: widget.label ?? '',
|
||||
onKey: (FocusNode node, RawKeyEvent evt) {
|
||||
if (evt is RawKeyDownEvent) {
|
||||
if (evt.logicalKey == LogicalKeyboardKey.escape) {
|
||||
widget.onEditingCancel?.call();
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
|
||||
return KeyEventResult.ignored;
|
||||
},
|
||||
canRequestFocus: true,
|
||||
);
|
||||
// Listen for focus out events
|
||||
_focusNode
|
||||
.addListener(() => widget.onFocusChanged?.call(_focusNode.hasFocus));
|
||||
widget.onFocusCreated?.call(_focusNode);
|
||||
if (widget.autoFocus ?? false) {
|
||||
scheduleMicrotask(() => _focusNode.requestFocus());
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void clear() => _controller.clear();
|
||||
|
||||
String get text => _controller.text;
|
||||
|
||||
set text(String value) => _controller.text = value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: Insets.sm),
|
||||
child: TextFormField(
|
||||
onChanged: widget.onChanged,
|
||||
onEditingComplete: widget.onEditingComplete,
|
||||
onFieldSubmitted: widget.onFieldSubmitted,
|
||||
onSaved: widget.onSaved,
|
||||
onTap: widget.onTap,
|
||||
autofocus: widget.autoFocus ?? false,
|
||||
focusNode: _focusNode,
|
||||
keyboardType: widget.type,
|
||||
obscureText: widget.obscureText ?? false,
|
||||
autocorrect: widget.autoCorrect ?? false,
|
||||
enableSuggestions: widget.enableSuggestions ?? false,
|
||||
style: widget.style ?? TextStyles.Body1,
|
||||
cursorColor: theme.accent1,
|
||||
controller: _controller,
|
||||
showCursor: true,
|
||||
enabled: widget.enabled,
|
||||
maxLines: widget.maxLines,
|
||||
textCapitalization: widget.capitalization ?? TextCapitalization.none,
|
||||
decoration: widget.inputDecoration ??
|
||||
InputDecoration(
|
||||
prefixIcon: widget.prefixIcon,
|
||||
suffixIcon: widget.suffixIcon,
|
||||
contentPadding:
|
||||
widget.contentPadding ?? EdgeInsets.all(Insets.m),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide.none),
|
||||
isDense: true,
|
||||
icon: widget.icon == null ? null : Icon(widget.icon),
|
||||
errorText: widget.errorText,
|
||||
errorMaxLines: 2,
|
||||
hintText: widget.hintText,
|
||||
hintStyle: TextStyles.Body1.textColor(theme.grey),
|
||||
labelText: widget.label),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ThinUnderlineBorder extends InputBorder {
|
||||
/// Creates an underline border for an [InputDecorator].
|
||||
///
|
||||
/// The [borderSide] parameter defaults to [BorderSide.none] (it must not be
|
||||
/// null). Applications typically do not specify a [borderSide] parameter
|
||||
/// because the input decorator substitutes its own, using [copyWith], based
|
||||
/// on the current theme and [InputDecorator.isFocused].
|
||||
///
|
||||
/// The [borderRadius] parameter defaults to a value where the top left
|
||||
/// and right corners have a circular radius of 4.0. The [borderRadius]
|
||||
/// parameter must not be null.
|
||||
const ThinUnderlineBorder({
|
||||
BorderSide borderSide = const BorderSide(),
|
||||
this.borderRadius = const BorderRadius.only(
|
||||
topLeft: Radius.circular(4.0),
|
||||
topRight: Radius.circular(4.0),
|
||||
),
|
||||
}) : super(borderSide: borderSide);
|
||||
|
||||
/// The radii of the border's rounded rectangle corners.
|
||||
///
|
||||
/// When this border is used with a filled input decorator, see
|
||||
/// [InputDecoration.filled], the border radius defines the shape
|
||||
/// of the background fill as well as the bottom left and right
|
||||
/// edges of the underline itself.
|
||||
///
|
||||
/// By default the top right and top left corners have a circular radius
|
||||
/// of 4.0.
|
||||
final BorderRadius borderRadius;
|
||||
|
||||
@override
|
||||
bool get isOutline => false;
|
||||
|
||||
@override
|
||||
UnderlineInputBorder copyWith(
|
||||
{BorderSide? borderSide, BorderRadius? borderRadius}) {
|
||||
return UnderlineInputBorder(
|
||||
borderSide: borderSide ?? this.borderSide,
|
||||
borderRadius: borderRadius ?? this.borderRadius,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
EdgeInsetsGeometry get dimensions {
|
||||
return EdgeInsets.only(bottom: borderSide.width);
|
||||
}
|
||||
|
||||
@override
|
||||
UnderlineInputBorder scale(double t) {
|
||||
return UnderlineInputBorder(borderSide: borderSide.scale(t));
|
||||
}
|
||||
|
||||
@override
|
||||
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
|
||||
return Path()
|
||||
..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width,
|
||||
math.max(0.0, rect.height - borderSide.width)));
|
||||
}
|
||||
|
||||
@override
|
||||
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
|
||||
return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
|
||||
}
|
||||
|
||||
@override
|
||||
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
|
||||
if (a is UnderlineInputBorder) {
|
||||
final newBorderRadius =
|
||||
BorderRadius.lerp(a.borderRadius, borderRadius, t);
|
||||
|
||||
if (newBorderRadius != null) {
|
||||
return UnderlineInputBorder(
|
||||
borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
|
||||
borderRadius: newBorderRadius,
|
||||
);
|
||||
}
|
||||
}
|
||||
return super.lerpFrom(a, t);
|
||||
}
|
||||
|
||||
@override
|
||||
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
|
||||
if (b is UnderlineInputBorder) {
|
||||
final newBorderRadius =
|
||||
BorderRadius.lerp(b.borderRadius, borderRadius, t);
|
||||
if (newBorderRadius != null) {
|
||||
return UnderlineInputBorder(
|
||||
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
|
||||
borderRadius: newBorderRadius,
|
||||
);
|
||||
}
|
||||
}
|
||||
return super.lerpTo(b, t);
|
||||
}
|
||||
|
||||
/// Draw a horizontal line at the bottom of [rect].
|
||||
///
|
||||
/// The [borderSide] defines the line's color and weight. The `textDirection`
|
||||
/// `gap` and `textDirection` parameters are ignored.
|
||||
/// @override
|
||||
|
||||
@override
|
||||
void paint(
|
||||
Canvas canvas,
|
||||
Rect rect, {
|
||||
double? gapStart,
|
||||
double gapExtent = 0.0,
|
||||
double gapPercentage = 0.0,
|
||||
TextDirection? textDirection,
|
||||
}) {
|
||||
if (borderRadius.bottomLeft != Radius.zero ||
|
||||
borderRadius.bottomRight != Radius.zero) {
|
||||
canvas.clipPath(getOuterPath(rect, textDirection: textDirection));
|
||||
}
|
||||
canvas.drawLine(rect.bottomLeft, rect.bottomRight, borderSide.toPaint());
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is InputBorder && other.borderSide == borderSide;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => borderSide.hashCode;
|
||||
}
|
29
app_flowy/packages/flowy_style/lib/text_field_container.dart
Normal file
29
app_flowy/packages/flowy_style/lib/text_field_container.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TextFieldContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
const TextFieldContainer({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<Widget>('child', child));
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.7.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -35,7 +35,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -64,6 +64,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.0-nullsafety.2"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: equatable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -95,6 +102,13 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
lint:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lint
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.3"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -115,7 +129,14 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -123,6 +144,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -156,6 +184,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
styled_widget:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: styled_widget
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.1+2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -169,7 +204,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.1"
|
||||
textstyle_extensions:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -17,6 +17,9 @@ dependencies:
|
||||
textstyle_extensions: '2.0.0-nullsafety'
|
||||
animations: ^2.0.0
|
||||
dartz: '0.10.0-nullsafety.2'
|
||||
provider: ^5.0.0
|
||||
styled_widget: '>=0.3.1'
|
||||
equatable: '>=2.0.2'
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -197,6 +197,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
expandable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: expandable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.4"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -233,7 +240,7 @@ packages:
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
flowy_logger:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "packages/flowy_logger"
|
||||
relative: true
|
||||
@ -401,6 +408,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
lint:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lint
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.3"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -599,6 +613,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
sized_context:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sized_context
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -653,6 +674,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
styled_widget:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: styled_widget
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.1+2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -702,6 +730,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
universal_platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -35,6 +35,8 @@ dependencies:
|
||||
path: packages/flowy_style
|
||||
flowy_editor:
|
||||
path: packages/flowy_editor
|
||||
flowy_logger:
|
||||
path: packages/flowy_logger
|
||||
|
||||
# third party packages
|
||||
time: '>=2.0.0'
|
||||
@ -48,6 +50,9 @@ dependencies:
|
||||
url: git://github.com/google/flutter-desktop-embedding.git
|
||||
path: plugins/window_size
|
||||
ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
|
||||
sized_context: ^1.0.0+1
|
||||
styled_widget: '>=0.3.1'
|
||||
expandable: ^4.1.4
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
@ -1,15 +1,15 @@
|
||||
mod sign_in;
|
||||
mod sign_up;
|
||||
mod user_detail;
|
||||
mod user_email;
|
||||
mod user_id;
|
||||
mod user_name;
|
||||
mod user_password;
|
||||
mod user_status;
|
||||
|
||||
pub use sign_in::*;
|
||||
pub use sign_up::*;
|
||||
pub use user_detail::*;
|
||||
pub use user_email::*;
|
||||
pub use user_id::*;
|
||||
pub use user_name::*;
|
||||
pub use user_password::*;
|
||||
pub use user_status::*;
|
||||
|
@ -1,8 +1,5 @@
|
||||
// Auto-generated, do not edit
|
||||
|
||||
mod user_status;
|
||||
pub use user_status::*;
|
||||
|
||||
mod sign_up;
|
||||
pub use sign_up::*;
|
||||
|
||||
@ -15,5 +12,8 @@ pub use user_table::*;
|
||||
mod errors;
|
||||
pub use errors::*;
|
||||
|
||||
mod user_detail;
|
||||
pub use user_detail::*;
|
||||
|
||||
mod event;
|
||||
pub use event::*;
|
||||
|
@ -17,7 +17,7 @@
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_results)]
|
||||
//! Generated file from `user_status.proto`
|
||||
//! Generated file from `user_detail.proto`
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
@ -309,28 +309,28 @@ impl ::protobuf::reflect::ProtobufValue for UserStatus {
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x11user_status.proto\"[\n\nUserDetail\x12\x14\n\x05email\x18\x01\x20\
|
||||
\n\x11user_detail.proto\"[\n\nUserDetail\x12\x14\n\x05email\x18\x01\x20\
|
||||
\x01(\tR\x05email\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12#\n\
|
||||
\x06status\x18\x03\x20\x01(\x0e2\x0b.UserStatusR\x06status*1\n\nUserStat\
|
||||
us\x12\x0b\n\x07Unknown\x10\0\x12\t\n\x05Login\x10\x01\x12\x0b\n\x07Expi\
|
||||
red\x10\x02J\xe2\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\x12\x03\0\
|
||||
\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\
|
||||
\x02\x08\x12\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x15\n\x0c\n\x05\x04\
|
||||
\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\
|
||||
\x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x13\x14\n\x0b\n\x04\x04\
|
||||
\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\
|
||||
\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\
|
||||
\0\x02\x01\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\
|
||||
\x04\x1a\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x05\x04\x0e\n\x0c\n\x05\
|
||||
\x04\0\x02\x02\x01\x12\x03\x05\x0f\x15\n\x0c\n\x05\x04\0\x02\x02\x03\x12\
|
||||
\x03\x05\x18\x19\n\n\n\x02\x05\0\x12\x04\x07\0\x0b\x01\n\n\n\x03\x05\0\
|
||||
\x01\x12\x03\x07\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x08\x04\x10\n\
|
||||
\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x08\x04\x0b\n\x0c\n\x05\x05\0\x02\0\
|
||||
\x02\x12\x03\x08\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\t\x04\x0e\n\
|
||||
\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\t\x04\t\n\x0c\n\x05\x05\0\x02\x01\
|
||||
\x02\x12\x03\t\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\n\x04\x10\n\x0c\n\
|
||||
\x05\x05\0\x02\x02\x01\x12\x03\n\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\
|
||||
\x12\x03\n\x0e\x0fb\x06proto3\
|
||||
red\x10\x02J\xe2\x02\n\x06\x12\x04\0\0\n\x01\n\x08\n\x01\x0c\x12\x03\0\0\
|
||||
\x12\n\n\n\x02\x04\0\x12\x04\x01\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\
|
||||
\x01\x08\x12\n\x0b\n\x04\x04\0\x02\0\x12\x03\x02\x04\x15\n\x0c\n\x05\x04\
|
||||
\0\x02\0\x05\x12\x03\x02\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x02\
|
||||
\x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x02\x13\x14\n\x0b\n\x04\x04\
|
||||
\0\x02\x01\x12\x03\x03\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x03\
|
||||
\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x03\x0b\x0f\n\x0c\n\x05\x04\
|
||||
\0\x02\x01\x03\x12\x03\x03\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x04\
|
||||
\x04\x1a\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x04\x04\x0e\n\x0c\n\x05\
|
||||
\x04\0\x02\x02\x01\x12\x03\x04\x0f\x15\n\x0c\n\x05\x04\0\x02\x02\x03\x12\
|
||||
\x03\x04\x18\x19\n\n\n\x02\x05\0\x12\x04\x06\0\n\x01\n\n\n\x03\x05\0\x01\
|
||||
\x12\x03\x06\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x10\n\x0c\n\
|
||||
\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\
|
||||
\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x0e\n\x0c\n\
|
||||
\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\
|
||||
\x12\x03\x08\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x10\n\x0c\n\
|
||||
\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\
|
||||
\x12\x03\t\x0e\x0fb\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
@ -1,5 +1,4 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message UserDetail {
|
||||
string email = 1;
|
||||
string name = 2;
|
@ -11,10 +11,10 @@ pub struct User {
|
||||
pub(crate) name: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub(crate) email: String,
|
||||
password: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
password: String,
|
||||
pub(crate) email: String,
|
||||
}
|
||||
|
||||
impl User {
|
||||
|
Loading…
Reference in New Issue
Block a user