Skip to content

Commit

Permalink
Merge pull request #1 from tofylion/improvement/organization
Browse files Browse the repository at this point in the history
Improvement/organization
  • Loading branch information
tofylion authored Jul 17, 2023
2 parents 52f12f2 + b6e98f4 commit 72a181b
Show file tree
Hide file tree
Showing 42 changed files with 198 additions and 123 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ migrate_working_dir/
.flutter-plugins-dependencies
.packages
.pub-cache/
pubspec.lock
.pub/
/build/

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 27 additions & 0 deletions assets/video_ids/youtube_ids.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"48dcd3_00-06-00": "C51M5R2NBBA",
"48dcd3_00-15-00": "Og6BSeZIL3s",
"48dcd3_00-25-00": "ZgupBRtBWjs",
"48dcd3_01-05-00": "XuSbsjphvJA",
"48dcd3_01-10-00": "2ivnkuewxKM",
"ad969d_00-00-30": "Pg1sWkt-YWg",
"ad969d_00-15-00": "SQrTn2gmqps",
"ad969d_00-43-00": "38hitgoLLQs",
"ad969d_01-11-00": "P_o90PO12Tw",
"ad969d_01-35-00": "Eb6y-SnGvKE",
"e0e547_00-00-00": "gU5IdCxgI1k",
"e0e547_00-08-00": "G2dgLw9Gsw0",
"e0e547_00-15-00": "mHbe2YpsN8s",
"e0e547_00-50-00": "IzCrrWyhDGU",
"e0e547_01-00-00": "j14fZMQRkC0",
"e8a35a_00-02-00": "dS5L-4ibJf0",
"e8a35a_00-07-00": "BaunHoekZYw",
"e8a35a_00-14-00": "sb0wimGysUY",
"e8a35a_01-05-00": "7-Y-Z4kcJvo",
"e8a35a_01-14-00": "7kk4NRfAff4",
"ec7a6a_00-30-00": "ta7R86C2aqI",
"ec7a6a_00-53-00": "-Q1mXZFole8",
"ec7a6a_01-19-00": "rwHyDwB04-4",
"ec7a6a_01-30-00": "lznuZ1bPlrs",
"ec7a6a_01-40-00": "gcFLTwbAncE"
}
3 changes: 3 additions & 0 deletions lib/constants/dimensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ class Dimensions {

static double get inputBoxWidth => 537.sp;
static double get inputBoxHeight => 62.sp;
static double get inputBoxLocation => 154.sp;

static double get actionButtonWidth => 211.sp;
static double get actionButtonHeight => 45.sp;
static double get actionButtonLocation => 258.sp;

static double get videoPlayerWidth => 1280.sp;
static double get videoPlayerHeight => 720.sp;
static double get videoPlayerLocation => 55.sp;

static double get backButtonHeight => 42.sp;
static double get backButtonWidth => 149.sp;
Expand Down
1 change: 1 addition & 0 deletions lib/constants/timing.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class Timing {
static const Duration zero = Duration.zero;
static const Duration inputShadowDuration = Duration(milliseconds: 100);
static const Duration mainTransitionDuration = Duration(milliseconds: 750);
}
33 changes: 6 additions & 27 deletions lib/constants/video_ids.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
const videoIds = {
'48dcd3_00-06-00': 'C51M5R2NBBA',
'48dcd3_00-15-00': 'Og6BSeZIL3s',
'48dcd3_00-25-00': 'ZgupBRtBWjs',
'48dcd3_01-05-00': 'XuSbsjphvJA',
'48dcd3_01-10-00': '2ivnkuewxKM',
'ad969d_00-00-30': 'Pg1sWkt-YWg',
'ad969d_00-15-00': 'SQrTn2gmqps',
'ad969d_00-43-00': '38hitgoLLQs',
'ad969d_01-11-00': 'P_o90PO12Tw',
'ad969d_01-35-00': 'Eb6y-SnGvKE',
'e0e547_00-00-00': 'gU5IdCxgI1k',
'e0e547_00-08-00': 'G2dgLw9Gsw0',
'e0e547_00-15-00': 'mHbe2YpsN8s',
'e0e547_00-50-00': 'IzCrrWyhDGU',
'e0e547_01-00-00': 'j14fZMQRkC0',
'e8a35a_00-02-00': 'dS5L-4ibJf0',
'e8a35a_00-07-00': 'BaunHoekZYw',
'e8a35a_00-14-00': 'sb0wimGysUY',
'e8a35a_01-05-00': '7-Y-Z4kcJvo',
'e8a35a_01-14-00': '7kk4NRfAff4',
'ec7a6a_00-30-00': 'ta7R86C2aqI',
'ec7a6a_00-53-00': '-Q1mXZFole8',
'ec7a6a_01-19-00': 'rwHyDwB04-4',
'ec7a6a_01-30-00': 'lznuZ1bPlrs',
'ec7a6a_01-40-00': 'gcFLTwbAncE'
};
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:annotations_helper/services/json_utils.dart';

final videoIdsProvider = FutureProvider<Map<String, dynamic>>((ref) async {
return loadJson('youtube_ids.json', assetPath: 'video_ids');
});
File renamed without changes.
85 changes: 30 additions & 55 deletions lib/main_screen.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:annotations_helper/constants/app_colors.dart';
import 'package:annotations_helper/constants/app_text_styles.dart';
import 'package:annotations_helper/constants/dimensions.dart';
import 'package:annotations_helper/main_screen_animator.dart';
import 'package:annotations_helper/main_screen_view_model.dart';
import 'package:annotations_helper/widgets/input_box.dart';
import 'package:annotations_helper/widgets/main_action_button.dart';
Expand All @@ -9,7 +10,6 @@ import 'package:annotations_helper/yt_video_player.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:sprung/sprung.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';

class MainScreen extends ConsumerStatefulWidget {
Expand All @@ -20,39 +20,43 @@ class MainScreen extends ConsumerStatefulWidget {

class _MainScreenState extends ConsumerState<MainScreen>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late CurvedAnimation _curvedAnimationController;
late Animation<double> _inputBoxMoveAnimation;
late Animation<double> _mainActionButtonMoveAnimation;
late Animation<double> _mainActionButtonWidthAnimation;
late Animation<double> _mainActionButtonHeightAnimation;
late Animation<double> _backButtonAnimation;

bool videoExpanded = false;
late MainScreenAnimator _controller;

@override
void initState() {
super.initState();
_initAnimations();
_controller = MainScreenAnimator(
vsync: this, // the SingleTickerProviderStateMixin
);
_controller.addListener(() {
setState(() {}); //To make animation changes update the widgets
});
}

@override
Widget build(BuildContext context) {
final vmState = ref.watch(MainScreenViewModel.provider);
final vm = ref.read(MainScreenViewModel.provider.notifier);
final videoReady = ref.watch(vm.videoReady);
final videoExpanded = ref.watch(_controller.videoExpandedProvider);

switch (vmState) {
case MainScreenStates.playingVideo:
_controller.forward().whenComplete(() {
setState(() {
videoExpanded = true;
});
ref
.read(_controller.videoExpandedProvider.notifier)
.update((state) => true);
});
break;
case MainScreenStates.waitingForInput:
_controller.reverse();
videoExpanded = false;
// This is a hack to make sure the provider updates after the widgets have finished rebuilding
WidgetsBinding.instance.addPostFrameCallback((_) {
ref
.read(_controller.videoExpandedProvider.notifier)
.update((state) => false);
});

break;
}

Expand All @@ -66,26 +70,26 @@ class _MainScreenState extends ConsumerState<MainScreen>
alignment: Alignment.center,
children: <Widget>[
Positioned(
top: _inputBoxMoveAnimation.value,
top: _controller.inputBoxValue,
child: InputBox(
focusNode: vm.mainInputFocusNode,
controller: vm.textController,
onFieldSubmitted: (value) async =>
await vm.updateVideo(value)),
),
Positioned(
top: _mainActionButtonMoveAnimation.value,
top: _controller.mainActionButtonMoveValue,
child: videoReady
? Container(
width: _mainActionButtonWidthAnimation.value,
height: _mainActionButtonHeightAnimation.value,
width: _controller.mainActionButtonWidthValue,
height: _controller.mainActionButtonHeightValue,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.black,
boxShadow: [
BoxShadow(
color: AppColors.teal.withOpacity(
0.25 * _curvedAnimationController.value),
color: AppColors.teal
.withOpacity(0.25 * _controller.value),
blurRadius: 50,
spreadRadius: 0,
offset: const Offset(0, 0),
Expand All @@ -106,27 +110,27 @@ class _MainScreenState extends ConsumerState<MainScreen>
: const SizedBox.shrink(),
),
Positioned(
top: _mainActionButtonMoveAnimation.value,
top: _controller.mainActionButtonMoveValue,
child: !videoExpanded
? MainActionButton(
width: _mainActionButtonWidthAnimation.value,
height: _mainActionButtonHeightAnimation.value,
width: _controller.mainActionButtonWidthValue,
height: _controller.mainActionButtonHeightValue,
text: !videoReady ? 'Go' : '',
onTap: () async {
await vm.updateVideo(vm.textController.text);
})
: const SizedBox.shrink(),
),
Positioned(
top: _backButtonAnimation.value,
top: _controller.backButtonValue,
child: MyBackButton(
onTap: () => vm.backToInput(),
shadowOpacity: videoReady ? 0.25 : 0,
)),
Positioned(
bottom: 78.sp,
child: Opacity(
opacity: 1 - _curvedAnimationController.value,
opacity: 1 - _controller.value,
child: Center(
child: Text(
'Made with 🤍 by TofyLion',
Expand All @@ -141,33 +145,4 @@ class _MainScreenState extends ConsumerState<MainScreen>
}),
);
}

void _initAnimations() {
_controller = AnimationController(
vsync: this, // the SingleTickerProviderStateMixin
duration: const Duration(milliseconds: 750),
)..addListener(() {
setState(() {});
});
_curvedAnimationController = CurvedAnimation(
parent: _controller,
curve: Sprung.overDamped,
reverseCurve: Sprung.overDamped.flipped);
_inputBoxMoveAnimation =
Tween<double>(begin: 154.sp, end: -Dimensions.inputBoxHeight)
.animate(_curvedAnimationController);
_mainActionButtonMoveAnimation = Tween<double>(begin: 258.sp, end: 55.sp)
.animate(_curvedAnimationController);
_mainActionButtonWidthAnimation = Tween<double>(
begin: Dimensions.actionButtonWidth,
end: Dimensions.videoPlayerWidth)
.animate(_curvedAnimationController);
_mainActionButtonHeightAnimation = Tween<double>(
begin: Dimensions.actionButtonHeight,
end: Dimensions.videoPlayerHeight)
.animate(_curvedAnimationController);
_backButtonAnimation =
Tween<double>(begin: -Dimensions.backButtonHeight, end: 0)
.animate(_curvedAnimationController);
}
}
62 changes: 62 additions & 0 deletions lib/main_screen_animator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'package:annotations_helper/constants/dimensions.dart';
import 'package:annotations_helper/constants/timing.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:sprung/sprung.dart';

class MainScreenAnimator extends AnimationController {
MainScreenAnimator({required TickerProvider vsync}) : super(vsync: vsync) {
duration = Timing.mainTransitionDuration;
_initAnimations();
}

late CurvedAnimation _curvedAnimationController;
late Animation<double> _inputBoxMoveAnimation;
late Animation<double> _mainActionButtonMoveAnimation;
late Animation<double> _mainActionButtonWidthAnimation;
late Animation<double> _mainActionButtonHeightAnimation;
late Animation<double> _backButtonAnimation;

final videoExpandedProvider = StateProvider<bool>((ref) => false);

void _initAnimations() {
_curvedAnimationController = CurvedAnimation(
parent: this,
curve: Sprung.overDamped,
reverseCurve: Sprung.overDamped.flipped);
_inputBoxMoveAnimation = Tween<double>(
begin: Dimensions.inputBoxLocation,
end: -Dimensions.inputBoxHeight - 10.sp)
.animate(_curvedAnimationController);
_mainActionButtonMoveAnimation = Tween<double>(
begin: Dimensions.actionButtonLocation,
end: Dimensions.videoPlayerLocation)
.animate(_curvedAnimationController);
_mainActionButtonWidthAnimation = Tween<double>(
begin: Dimensions.actionButtonWidth,
end: Dimensions.videoPlayerWidth)
.animate(_curvedAnimationController);
_mainActionButtonHeightAnimation = Tween<double>(
begin: Dimensions.actionButtonHeight,
end: Dimensions.videoPlayerHeight)
.animate(_curvedAnimationController);
_backButtonAnimation =
Tween<double>(begin: -Dimensions.backButtonHeight - 10.sp, end: 0)
.animate(_curvedAnimationController);
}

double get animationValue => _curvedAnimationController.value;

double get inputBoxValue => _inputBoxMoveAnimation.value;

double get mainActionButtonMoveValue => _mainActionButtonMoveAnimation.value;

double get mainActionButtonWidthValue =>
_mainActionButtonWidthAnimation.value;

double get mainActionButtonHeightValue =>
_mainActionButtonHeightAnimation.value;

double get backButtonValue => _backButtonAnimation.value;
}
19 changes: 3 additions & 16 deletions lib/main_screen_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:annotations_helper/constants/video_ids.dart';
import 'package:annotations_helper/models/config.dart';
import 'package:annotations_helper/models/frame_id.dart';
import 'package:annotations_helper/services/json_utils.dart';
import 'package:annotations_helper/providers/frame_providers.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
Expand Down Expand Up @@ -64,14 +64,15 @@ class MainScreenViewModel extends StateNotifier<MainScreenStates> {
Future<void> updateVideo(String query) async {
final tempFrameId = FrameID.parseFrameID(query);
// Make sure that video name is valid

final videoIds = await ref.read(videoIdsProvider.future);
if (videoIds[tempFrameId.videoName] == null) {
// TODO: Show error message
return;
}

ref.read(frameIdProvider.notifier).update((state) => tempFrameId);
final videoId = videoIds[ref.read(frameIdProvider)!.videoName]!;

controller.loadVideoById(
videoId: videoId,
startSeconds: (await ref.read(frameTimestampProvider.future))! -
Expand All @@ -95,17 +96,3 @@ class MainScreenViewModel extends StateNotifier<MainScreenStates> {
);
}
}

// FrameID stateProvider
final frameIdProvider = StateProvider<FrameID?>((ref) => null);

// FrameTimestamp provider
final frameTimestampProvider = FutureProvider<double?>((ref) async {
final frame = ref.watch(frameIdProvider);
if (frame == null) {
return null;
}
final json = await loadJson('${frame.videoName}.json');

return json['${frame.frameNumber}'] / 1000.0; // convert to seconds
});
Loading

0 comments on commit 72a181b

Please sign in to comment.