Skip to content

Commit

Permalink
fix platforms and search button
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobaraujo7 committed Jan 16, 2024
1 parent e5990d6 commit 354aef5
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 137 deletions.
8 changes: 3 additions & 5 deletions lib/app/(public)/apps_page.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'package:asp/asp.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:yuno/app/core/services/game_service.dart';
import 'package:yuno/app/interactor/actions/apps_action.dart';
import 'package:yuno/app/interactor/atoms/gamepad_atom.dart';

import '../../injector.dart';
import '../interactor/atoms/app_atom.dart';
import '../interactor/atoms/config_atom.dart';
import '../interactor/services/gamepad_service.dart';

class AppsPage extends StatefulWidget {
const AppsPage({super.key});
Expand All @@ -21,9 +21,7 @@ class _AppsPageState extends State<AppsPage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();

final gamepadService = injector.get<GameService>();
_disposer = rxObserver(() => gamepadService.state, effect: (state) {
_disposer = rxObserver(() => gamepadState.value, effect: (state) {
if (gameConfigState.value.swapABXY && state == GamepadButton.buttonA) {
Navigator.of(context).pop();
} else if (state == GamepadButton.buttonB) {
Expand Down
9 changes: 4 additions & 5 deletions lib/app/(public)/config/config_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:asp/asp.dart';
import 'package:flutter/material.dart';
import 'package:yuno/app/interactor/atoms/config_atom.dart';
import 'package:yuno/injector.dart';

import '../../core/services/game_service.dart';
import '../../core/widgets/animated_title_app_bart.dart';
import '../../interactor/atoms/config_atom.dart';
import '../../interactor/atoms/gamepad_atom.dart';
import '../../interactor/services/gamepad_service.dart';
import 'widgets/about_widget.dart';
import 'widgets/feedback_widget.dart';
import 'widgets/platform_widget.dart';
Expand Down Expand Up @@ -44,8 +44,7 @@ class _ConfigPageState extends State<ConfigPage> {
void initState() {
super.initState();

final gamepadService = injector.get<GameService>();
_disposer = rxObserver(() => gamepadService.state, effect: (state) {
_disposer = rxObserver(() => gamepadState.value, effect: (state) {
if (gameConfigState.value.swapABXY && state == GamepadButton.buttonA) {
Navigator.of(context).pop();
} else if (state == GamepadButton.buttonB) {
Expand Down
13 changes: 5 additions & 8 deletions lib/app/(public)/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:routefly/routefly.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:yuno/app/core/services/game_service.dart';
import 'package:yuno/app/interactor/atoms/config_atom.dart';
import 'package:yuno/app/interactor/atoms/game_atom.dart';
import 'package:yuno/app/interactor/models/game.dart';
import 'package:yuno/injector.dart';
import 'package:yuno/routes.dart';

import '../core/assets/sounds.dart' as sounds;
Expand All @@ -20,6 +18,8 @@ import '../core/widgets/animated_title_app_bart.dart';
import '../core/widgets/background/background.dart';
import '../core/widgets/card_tile/card_tile.dart';
import '../core/widgets/command_bar.dart';
import '../interactor/atoms/gamepad_atom.dart';
import '../interactor/services/gamepad_service.dart';

Route routeBuilder(BuildContext context, RouteSettings settings) {
return PageRouteBuilder(
Expand Down Expand Up @@ -67,19 +67,16 @@ class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
final gamepadService = injector.get<GameService>();
_disposer = rxObserver(() => gamepadService.state, effect: (state) {
handleKey(state!);
});
_disposer = rxObserver(() => gamepadState.value, effect: handleKey);
}

bool allowPressed() {
return _lastOpenGameAt == null || //
DateTime.now().difference(_lastOpenGameAt!).inSeconds > 1;
}

void handleKey(GamepadButton event) {
if (Routefly.currentOriginalPath != routePaths.home) {
void handleKey(GamepadButton? event) {
if (Routefly.currentOriginalPath != routePaths.home || event == null) {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/app/(public)/splash_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:gap/gap.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:routefly/routefly.dart';
import 'package:yuno/app/interactor/actions/gamepad_action.dart';
import 'package:yuno/routes.dart';

import '../core/assets/sounds.dart' as sounds;
Expand All @@ -21,6 +22,7 @@ class _AppPageState extends State<AppPage> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
registerGamepad();
Future.wait([
apps.fetchApps(),
game.firstInitialization(context),
Expand Down
77 changes: 65 additions & 12 deletions lib/app/core/widgets/animated_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,63 +15,116 @@ class AnimatedSearch extends StatefulWidget {
class _AnimatedSearchState extends State<AnimatedSearch>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
late final Animation<double> iconSizeAnimation;
late final Animation<double> sizeFieldAnimation;
late final Animation<double> iconRotationAnimation;

final _focusNode = FocusNode();

@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
duration: const Duration(milliseconds: 700),
);
_controller.addListener(() {
setState(() {});
});

const iconMaxSize = 30.0;
const iconMinSize = 1.0;

iconSizeAnimation = TweenSequence(
[
TweenSequenceItem(
tween: Tween<double>(begin: iconMaxSize, end: iconMinSize),
weight: 20,
),
TweenSequenceItem(
tween: Tween<double>(begin: iconMinSize, end: iconMinSize),
weight: 60,
),
TweenSequenceItem(
tween: Tween<double>(begin: iconMinSize, end: iconMaxSize),
weight: 20,
),
],
).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.0, 0.7),
reverseCurve: const Interval(0.0, 1.0),
),
);

sizeFieldAnimation = Tween<double>(begin: 0, end: 250).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.0, 0.5, curve: Curves.easeOut),
reverseCurve: const Interval(0.4, 1.0, curve: Curves.easeIn),
),
);

iconRotationAnimation = Tween<double>(begin: 0, end: pi).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.6, 1.0, curve: Curves.elasticOut),
reverseCurve: Curves.ease,
),
);
}

@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final sizeAnimation = Tween<double>(begin: 0, end: 250).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeOut,
reverseCurve: Curves.easeIn,
),
);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Transform.rotate(
angle: _controller.value * pi,
child: Icon(_controller.value != 0 ? Icons.close : Icons.search),
angle: iconRotationAnimation.value,
child: Icon(
_controller.value >= 0.5 ? Icons.close : Icons.search,
size: iconSizeAnimation.value,
),
),
onPressed: () {
if (_controller.value == 0) {
_controller.forward();
_focusNode.requestFocus();
} else {
widget.onChanged('');
_controller.reverse();
_focusNode.unfocus();
}
},
),
if (_controller.value != 0)
SizedBox(
width: sizeAnimation.value,
width: sizeFieldAnimation.value,
child: TextField(
autofocus: true,
focusNode: _focusNode,
onChanged: widget.onChanged,
decoration: const InputDecoration(
hintText: 'Search a Game',
border: InputBorder.none,
),
),
),
if (_focusNode.hasFocus)
IconButton(
onPressed: () {
_focusNode.unfocus();
},
icon: const Icon(Icons.keyboard_hide),
),
const Gap(5),
],
);
Expand Down
58 changes: 58 additions & 0 deletions lib/app/data/apps/android_apps_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:android_intent_plus/android_intent.dart' as android_intent;
import 'package:installed_apps/app_info.dart';
import 'package:installed_apps/installed_apps.dart' as installed_apps;

import '../../interactor/models/app_model.dart';
import '../../interactor/repositories/apps_repository.dart';

class AndroidAppsRepository implements AppsRepository {
@override
Future<Set<AppModel>> getInstalledApps() async {
List<AppInfo> apps =
await installed_apps.InstalledApps.getInstalledApps(true, true);

return apps.map((e) {
return AppModel(
name: e.name!,
package: e.packageName!,
icon: e.icon!,
);
}).toSet();
}

@override
Future<void> openApp(AppModel app) {
return installed_apps.InstalledApps.startApp(app.package);
}

@override
Future<void> openAppSettings(AppModel app) {
return installed_apps.InstalledApps.openSettings(app.package);
}

@override
Future<void> openConfiguration() async {
const intent = android_intent.AndroidIntent(
action: 'android.settings.SETTINGS',
);

await intent.launch();
}

@override
Future<void> openWithCustomConfig({
required String action,
String? package,
String? componentName,
Map<String, dynamic> arguments = const {},
}) async {
final intent = android_intent.AndroidIntent(
action: action,
package: package,
componentName: componentName,
arguments: arguments,
);

return intent.launch();
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
// ignore_for_file: constant_identifier_names
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';

import 'dart:async';
import '../../../interactor/services/gamepad_service.dart';

import 'package:asp/asp.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class AndroidGamepadService extends GamepadService {
static const _channel = MethodChannel('br.com.flutterando.yuno/gamepad');

enum GamepadButton {
buttonA,
buttonB,
buttonX,
buttonY,
leftStickUp,
leftStickDown,
leftStickLeft,
leftStickRight,
dpadUp,
dpadDown,
dpadLeft,
dpadRight,
leftThumb,
rightThumb,
start,
select,
LB,
RB,
}
AndroidGamepadService() {
_channel.setMethodCallHandler(_handleMethodCall);
}

extension GamepadButtonExtension on GamepadButton {
static GamepadButton fromMethod(String method) {
Future<void> _handleMethodCall(MethodCall call) async {
try {
final button = _fromMethod(call.method);
setEvent(button);
} catch (e) {
debugPrint('Erro ao processar evento do gamepad: $e');
}
}

GamepadButton _fromMethod(String method) {
switch (method) {
case 'buttonAPressed':
return GamepadButton.buttonA;
Expand Down Expand Up @@ -67,35 +58,3 @@ extension GamepadButtonExtension on GamepadButton {
}
}
}

class GameService {
static const _channel = MethodChannel('br.com.flutterando.yuno/gamepad');
final _state = Atom(
GamepadButton.buttonA,
pipe: throttleTime(const Duration(milliseconds: 200)),
);
GamepadButton get state => _state.value;

GameService() {
_channel.setMethodCallHandler(_handleMethodCall);
}

void launchApp(String packageName) {
_channel.invokeMethod('launchApp', {
'packageName': packageName,
});
}

Future<void> _handleMethodCall(MethodCall call) async {
try {
final button = GamepadButtonExtension.fromMethod(call.method);
_state.setValue(button);
} catch (e) {
debugPrint('Erro ao processar evento do gamepad: $e');
}
}

void dispose() {
_state.dispose();
}
}
9 changes: 9 additions & 0 deletions lib/app/interactor/actions/gamepad_action.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:yuno/injector.dart';

import '../atoms/gamepad_atom.dart';
import '../services/gamepad_service.dart';

void registerGamepad() {
final gamepad = injector.get<GamepadService>();
gamepad.setHandleFunction(gamepadState.setValue);
}
Loading

0 comments on commit 354aef5

Please sign in to comment.