FeedbackTabProvider

import'dart:async';
import'package:flutter/material.dart';
import'package:intl/intl.dart';
import'package:preload_page_view/preload_page_view.dart';
import'package:quickcheck/model/exam_result.dart';
import'package:quickcheck/model/feedbacks.dart'asfeedbacks;
import'package:quickcheck/model/recent_exam.dart'asRecentExam;
import'package:quickcheck/model/feedbacks.dart';
import'package:quickcheck/model/user.dart';
import'package:quickcheck/utils/ApiAdapter.dart';
import'package:quickcheck/utils/shared_prefs.dart';
import'package:quickcheck/view/MypageTab/feedback_list.dart';
import'package:quickcheck/view/feedback_tab/visibility_provider.dart';
import'package:sliding_up_panel/sliding_up_panel.dart';

classFeedbackTabProviderextendsChangeNotifier {
  ExamResult _examResult;
  FeedbackTabProvider(this._examResult);

  GetPoint getPoint;
// int userPoint;
int userId;

// bool showPluse = false;
  //미시청에서 시청으로 바뀔때 잠깐보여주는것
finalValueNotifier<bool> showPluse = ValueNotifier<bool>(false);

//전체 시험리스트
RecentExam.RecentExam _recentExam;
//최근시험 리스트
List<RecentExam.Results> resentExamHistory = [];

//TODO: playList, playListReversed, thumbnailLoadingIsDone등은 class따위로
//묶는 것이..
  //오늘 어제 전체 피드백영상 리스트
List<List<feedbacks.Results>> _playListAll = [];
//현제플레이되는 영상리스트 처음엔 미시청만
Map<int, List<feedbacks.Results>> playListUnviewd = {};
//key값으로 찾기
varplayListUnviewdKeys = [];

//실제 비디오 플레이시 사용되는 자료
// List<List<feedbacks.Results>> playListReversed = [];
List<List<List<bool>>> thumbnailLoadingIsDone = [];//가장 안쪽 List는 [0]은 thumbnail, [1]은 videoapp controller initialized

int colIndex = 0;
  int rowIndex = 0;
  int colIndexPlaylist = 0;
  int rowIndexPlaylist = 0;

  int unviewCount = 0;
  int pageInt = 0;
  bool loop =true;
  bool _visibility =true;
  Timer _timer = Timer(Duration(seconds: 0), () =>null);
  PanelController panelController = PanelController();
  PreloadPageController pageControllerMain =
      PreloadPageController(initialPage: 0, keepPage:true,);

  int urlId = 0;
//포인트숫자 올라가기전
int userPointRecord = 0;
//포인트 숫자 올라간 후
finalValueNotifier<int> userPoint = ValueNotifier<int>(0);

  bool initReady =false;
  bool favorate =false;
  bool panelOpen =false;

finalValueNotifier<bool> pageMoving = ValueNotifier<bool>(false);
// bool _pageMoving = false;

  //index오류
// List<List<feedbacks.Results>> get playList => _playList;
List<List<feedbacks.Results>>getplayList => _playListAll;

//unviewd만

// feedbacks.Results get currentFeedback => _playList[colIndex][rowIndex];
feedbacks.ResultsgetcurrentFeedback => playListUnviewd.values.elementAt(colIndex)[rowIndex];
  feedbacks.ResultsgetcurrentFeedbackPlaylist => playListUnviewd.values.elementAt(colIndexPlaylist)[rowIndexPlaylist];

finalValueNotifier<int> counterInt = ValueNotifier<int>(0);

// bool get loop => _loop;

boolgetvisibility => _visibility;

// bool get pageMoving => _pageMoving;

Timergettimer => _timer;

  ExamResultgetexamResult => _examResult;

  List<String> panelImage = [];
  List<String> panelImageForPanel = [];

  setVisibility(bool visibility) {
    _visibility = visibility;
    currentVisibility.setVisibility(visibility);

    notifyListeners();
  }

  setPageMoving(bool pageMovingState) {
    pageMoving.value = pageMovingState;
// print('change change change change change change ');
    // print('change change change change change change ${pageMoving.value}');
    // _pageMoving = pageMoving;

notifyListeners();
  }

  setTimer(Timer timer) => _timer = timer;

  cancelTimer() => _timer.cancel();

  Future<void> init(int count)async{

if(count !=null){
      unviewCount = count;
    }

    _recentExam =awaitApiAdapter.getRecentExams(
        size: 200, state: 'E', noAssignment:false);

// DateFormat.yMMMd().format(DateTime.now()) != DateFormat.yMMMd().format(DateTime.parse(_recentExam.results.first.createdAt).toLocal())
    //최근 시험 데이터 받아오기
// if (DateTime.now().difference(DateTime.parse(_recentExam.results.first.createdAt).toLocal()).inDays == 0) {
if(DateFormat.yMMMd().format(DateTime.now()) == DateFormat.yMMMd().format(DateTime.parse(_recentExam.results.first.createdAt).toLocal())) {
//마지막 시험본게 오늘일 경우,오늘 시험만을 가져옴.
_recentExam.results.forEach((e) {
// if (DateTime.now().difference(DateTime.parse(e.createdAt).toLocal()).inDays == 0) {
if(DateFormat.yMMMd().format(DateTime.now()) == DateFormat.yMMMd().format(DateTime.parse(e.createdAt).toLocal())) {
// print('이거???이거??? ${e.exam.chapter}챕터 : ${e.exam.questionType.id}회차');
resentExamHistory.add(e);
        }
      });
      print(
          'resentExamHistory resentExamHistory resentExamHistory ${resentExamHistory.length}');
// resentExamHistory.add(value);

}else if(DateFormat.yMMMd().format(DateTime.now()) != DateFormat.yMMMd().format(DateTime.parse(_recentExam.results.first.createdAt).toLocal())) {
//마지막 시험본게 어제일 경우,어제의 피드백을 가져 옴.
_recentExam.results.forEach((e) {
if(DateFormat.yMMMd().format(DateTime.parse(_recentExam.results.first.createdAt).toLocal()) == DateFormat.yMMMd().format(DateTime.parse(e.createdAt).toLocal())) {
// print('이전1이전1이전1이전1이전1이전1이전1이전1이전1이전1이전1이전1이전1이전1 ');
          // print('이거???이거??? ${e.exam.chapter}챕터 : ${e.exam.questionType.id}회차');
resentExamHistory.add(e);
        }
      });
    }

//시험 데이터를 기반으로 데이터 받아오기 (_feedbackList채우기)
    // _feedbackList = [qid1, qid2, qid3]
List<List<feedbacks.Results>> _feedbackList = [];
if(resentExamHistory.length != 0) {
// for문 방식
//전체 시험들을 iterate
print('resentExamHistory.length resentExamHistory.length ${resentExamHistory.length}');
for(vari = 0; i < resentExamHistory.length; i++) {
//각각의 question type들을 전부 iterate
        //TODO:가장 최근에 본 시험이 chapter 10의 1회차, chapter 2의 3회차 라면,
//아래 for loop은 1회차 시험만 보는 것이 아닌가요?
        // for (var j = 0; j < resentExamHistory[0].exam.questionType.id; j++) {
int latestQuestiontypeId = 3;
for(varj = 0; j < latestQuestiontypeId; j++) {
//전체 시험들을 통해,각각의 exam.id와 questionTypeId를 구하고,
          //이를 이용하여 getFeedbackList()
print('resentExamHistory[i].exam.id resentExamHistory[i].exam.id ${resentExamHistory[i].exam.id}');
          Feedbacks result =awaitApiAdapter.getFeedbackList(
              resentExamHistory[i].exam.id,
              questionType: j + 1);
//여기 물어볼것 questionType 1로받고 questionType 2로받았을때 questionType 1과 questionType 2가 다를수도있으니 로직이 잘못됬을수도...
if(result.results.isNotEmpty) {
            _feedbackList.add(result.results.map((e) => e).toList());
// sort by voca id
_feedbackList[j].sort((a, b) =>
                a.feedback.vocabulary.id.compareTo(b.feedback.vocabulary.id));
            print('_feedbackList _feedbackList ${_feedbackList[0].length}');
          }
        }
      }
    }

// _playList를 완성.
    //   _playList = [voca1, voca2, ..., vocaN]
    //전체 vocabulary개수를 알 수 없기 때문에, Map(rawPlayList)을 일단 만들고,
    //이후에 _playList를 채움.
Map<int, List<feedbacks.Results>> rawPlayList =
        {};//이것을 기반으로 _playList만듬.
_feedbackList.forEach((elemList) {
      elemList.forEach((elem) {
        int key = elem.feedback.vocabulary.id;
if(rawPlayList.containsKey(key)) {
          rawPlayList[key].add(elem);
        }else{
          rawPlayList[key] = [elem];
        }
      });
    });

// rawPlayList -> _playList
List<int> sortedKeys = rawPlayList.keys.toList();

// sorting first
sortedKeys.forEach((element) {
      rawPlayList[element].sort(
          (a, b) => a.feedback.level.compareTo(b.feedback.level));// sort first
      //플레이리스트 추가
_playListAll.add(rawPlayList[element].toList());// add to playlist
});

//암본것 위로 올리기
// sortedKeys.forEach((element) {
    //     //플레이리스트 추가
//       _playList.add(rawPlayList[element].toList()); // add to playlist
    //   });

    // // then add unviewed
    // sortedKeys.forEach((element) {
    //   // last가 가장 최근 피드백 영상일 것임.
    //   //최근 피드백 영상이 항상 포커스이므로 이 모델을 기준으로 추가.
    //   if (rawPlayList[element].last.viewed == false) {
    //     _playList.add(rawPlayList[element].toList()); // add to playlist
    //   }
    // });
    //
    // // add viewed
    // sortedKeys.forEach((element) {
    //   //그 외 이미 본 단어들을 추가
//   if (rawPlayList[element].last.viewed) {
    //     _playList.add(rawPlayList[element].toList()); // add to playlist
    //   }
    // });

    // _playList -> playListReversed and panelImage
    //_playList의 자료는 형식이 {{3,2,1},{3,2,1},{3,2,1}}로 되어있어서 .reversed를 통해서 순서를 바꾸어줍니다
//실제 사용하는건 = playListReversed입니다
for(vari = 0; i < _playListAll.length; i++) {
// playListReversed.add(_playList[i].reversed.toList());
      //순서때문에 .first가
panelImageForPanel.add(_playListAll[i].last.feedback.thumbnail);
// thumbnailLoadingIsDone.add(_playList[i].map((_) => [false, false]).toList());
if(!_playListAll[i].last.viewed){
        playListUnviewd.addAll({i : _playListAll[i].toList()});
      }
    }

    playListUnviewdKeys.add(playListUnviewd);

for(vari = 0; i < playListUnviewd.keys.length; i++){
      panelImage.add(playListUnviewd.values.elementAt(i).last.feedback.thumbnail);
      thumbnailLoadingIsDone.add(playListUnviewd.values.elementAt(i).map((_) => [false,false]).toList());
    }

  print('playListUnviewd playListUnviewd ${playListUnviewd.keys}');

    userId = SharedPrefs().userId;
//현제 포인트
ApiAdapter.getUserPoint(userId).then((value) {
      getPoint = value;
      userPoint.value = value.pointResults.first.amount;
      userPointRecord = value.pointResults.first.amount;
    });

    colIndex = 0;
    rowIndex = _playListAll[0].length - 1;
// rowIndex = playListReversed[0].length - 1;
favorate = currentFeedback.saved;

    initReady =true;

    notifyListeners();

  }

//시청완료인것을 눌렀을때 화면에 추가하고 다시띄줘주기
voidsetplayListUnviewd2(int index){
    print('playListUnviewd playListUnviewd ${playListUnviewd.keys}');
//추가
playListUnviewd.addAll({index : _playListAll[index].toList()});
varmapEntries = playListUnviewd.entries.toList()
      ..sort((a, b) => a.key.compareTo(b.key));
    playListUnviewd
      ..clear()
      ..addEntries(mapEntries);

  print('playListUnviewd2 playListUnviewd2 ${playListUnviewd.keys}');
//비워주기
panelImage.clear();
    thumbnailLoadingIsDone.clear();
    playListUnviewdKeys.clear();

for(vari = 0; i < playListUnviewd.keys.length; i++){
      panelImage.add(playListUnviewd.values.elementAt(i).last.feedback.thumbnail);
      thumbnailLoadingIsDone.add(playListUnviewd.values.elementAt(i).map((_) => [false,false]).toList());
    }

    playListUnviewdKeys.add(playListUnviewd);

    notifyListeners();
  }

  Future<Feedbacks> getFeedbackList(int questionType) {
returnApiAdapter.getFeedbackList(_examResult.id,
        questionType: questionType);
  }

voidsetPoint() {
    userId = SharedPrefs().userId;
// int _selectedBookId = SharedPrefs().bookId;
    //현제 포인트
ApiAdapter.getUserPoint(userId).then((value) {
      userPoint.value = value.pointResults.first.amount;
    });
    notifyListeners();
  }

voidsetPointRecord(int point) {
    userPointRecord = point;
    notifyListeners();
  }

// void setSaved(int id, bool saved, int vertical, int horizontal){
voidsetSaved(int id, bool saved) {
    ApiAdapter.patchFeedback(id, saved: !saved);
    currentFeedback.saved = !saved;
    _playListAll[colIndex][rowIndex].saved = !saved;
// playListReversed[vertical][horizontal].saved = !saved;
notifyListeners();
  }

//좋아요 저장
voidsetliked(int id, bool liked, int vertical, int horizontal) {
    print('id id id id $id');
    ApiAdapter.patchFeedback(id, liked: liked);
// playListReversed[vertical][horizontal].liked = !liked;
_playListAll[vertical][horizontal].liked = !liked;
    notifyListeners();
  }

//현제 플레이되고있는 리스트의 가로 세로
setColindexRowIndex({int colIndexP , int rowIndexP}){
if(colIndexP !=null){
      colIndexPlaylist = colIndexP;
    }
if(rowIndexP !=null){
      rowIndexPlaylist = rowIndexP;
    }

    notifyListeners();
  }

voidsetPageInt(int page) {
    pageControllerMain =newPreloadPageController(initialPage: page);
    notifyListeners();
  }

//본거 안본거
voidsetView(int ver, int hori, int unviewedIndex) {
// playListReversed[ver][hori].viewed = true;
_playListAll[ver][hori].viewed =true;
    playListUnviewd.values.elementAt(unviewedIndex)[hori].viewed =true;
// for (var i = 0; i > _playList[ver].length; i++) {
    //   // if (playListReversed[ver][hori].id == _playList[ver][i].id) {
    //   if (_playList[ver][hori].id == _playList[ver][i].id) {
    //     _playList[ver][i].viewed = true;
    //   }
    // }
notifyListeners();
  }

voidsetPage(int page) {
    pageControllerMain.jumpToPage(page);
    setVisibility(false);
    currentVisibility.setVisibility(false);
    notifyListeners();
  }

//영상 저장
voidsetFavorate(bool _favorate) {
    favorate = _favorate;
    notifyListeners();
  }

//반복
voidsetLoop(bool loopState) {
    loop = loopState;
    notifyListeners();
  }

//panel열리고 닫히는것 확인
voidsetPanelOpen(bool open) {
if(open){
      panelController.open();
    }else if(!open){
      panelController.close();
    }
    panelOpen = open;

    notifyListeners();
  }

voidsetShowPluse(bool plus){
    showPluse.value = plus;

    notifyListeners();
  }

voidsetJumpPage(int page) {
// int different = 0;
    // int different = page - colIndex;
    // var index = playListUnviewd2.indexWhere((map) => map[page] == 0);
varindex;

for(vari = 0; i < playListUnviewd.keys.length; i++){
if(playListUnviewd.keys.elementAt(i) == page){
        index = i;
      }
    }
// pageControllerMain = new PreloadPageController(initialPage: index);
    // pageControllerMain.animateToPage(index, duration: Duration(milliseconds: 100), curve: Curves.fastOutSlowIn);
pageControllerMain.jumpToPage(index);
    print('index index index index index index index index ${index + 1}');
// // different.abs();
    // print('차이 차이 차이 ${different.abs()}');
    // print('12312312321312312313 123123123123123 ${page - colIndex}');
    // print('12312312321312312313 123123123123123 ${different.abs()}');
    // if (different.abs() != 0) {
    //   pageControllerMain.jumpToPage(page);
      // print('hdbfaijhdjkbnaskfnak;jsndf ${pageControllerMain.page}');
      // pageControllerMain.animateToPage(page,
      //     duration: Duration(milliseconds: 10),
      //     // curve: Curves.ease,
      //     curve: Curves.fastOutSlowIn);

      // pageControllerMain.jumpTo(page.toDouble());

      // Future.delayed(Duration(milliseconds: 500), () async {
      //   pageControllerMain.animateToPage(page,
      //       duration: different.abs() <= 2
      //           ? Duration(milliseconds: 500)
      //           : different.abs() > 2 && different.abs() < 7
      //               ? Duration(milliseconds: 1500)
      //               : Duration(milliseconds: 2200),
      //       // curve: Curves.ease,
      //       curve: Curves.fastOutSlowIn);
      // });
    // }

setVisibility(false);
    currentVisibility.setVisibility(false);

    notifyListeners();
  }
}

FeedbackTabPlay

import'package:flutter/foundation.dart';
import'package:flutter/material.dart';
import'package:flutter/painting.dart'asfp;
import'package:googleapis/gamesconfiguration/v1configuration.dart';
import'package:line_awesome_flutter/line_awesome_flutter.dart';
import'package:lottie/lottie.dart';
import'package:provider/provider.dart';
import'package:quickcheck/model/exam_result.dart';
import'package:quickcheck/utils/ApiAdapter.dart';
import'package:quickcheck/utils/show_message.dart';
import'package:quickcheck/view/Common/tab_page.dart';
import'package:quickcheck/view/Common/tab_page_provider.dart';
import'package:quickcheck/view/TestTab/feedback_play.dart';
import'package:quickcheck/model/recent_exam.dart'asRecentExam;
import'package:quickcheck/view/feedback_tab/feedback_recommend_video.dart';
import'package:quickcheck/view/feedback_tab/visibility_provider.dart';
import'package:sizer/sizer.dart';
import'../../theme_provider.dart';
import'dart:async';
import'dart:ui';
import'package:camera/camera.dart';
import'package:flutter/cupertino.dart';
import'package:flutter/material.dart';
import'package:flutter/services.dart';
import'package:intl/intl.dart';
import'package:mccounting_text/mccounting_text.dart';
import'package:preload_page_view/preload_page_view.dart';
import'package:provider/provider.dart';
import'package:quickcheck/model/exam_result.dart';
import'package:quickcheck/model/feedbacks.dart'asfeedbacks;
import'package:quickcheck/style.dart';
import'package:quickcheck/view/TestTab/preload_player.dart';
import'package:quickcheck/view/TestTab/preload_player_chewie.dart';
import'package:quickcheck/view/feedback_tab/feedback_tab_preload.dart';
import'package:quickcheck/view/feedback_tab/feedback_tab_provider.dart';
import'package:quickcheck/view/feedback_tab/visibility_provider.dart';
import'package:sliding_up_panel/sliding_up_panel.dart';
import'package:flutter_screenutil/flutter_screenutil.dart';
import'package:video_player/video_player.dart';
import'package:sizer/sizer.dart';

classFeedbackTabPlayextendsStatefulWidget {
  @override
  _FeedbackTabPlayState createState() => _FeedbackTabPlayState();
}

class_FeedbackTabPlayStateextendsState<FeedbackTabPlay> {
  RecentExam.RecentExam recentExam;
  ExamResult examResult = ExamResult();
  bool _isLoading =true;

  @override
voiddidChangeDependencies() {
super.didChangeDependencies();
    getReady();
  }

  getReady()async{
    recentExam =awaitApiAdapter.getRecentExams(
        size: 200, state: 'E', noAssignment:false);
    print(' _recentExam ${recentExam.results.length}');
    print(' _recentExam okok');
if(recentExam.results.length != 0) {
      examResult =awaitApiAdapter.getExamResult(recentExam.results.first.id);
      print(' examResult okok');
    }

if(mounted) {
      setState(() {
        _isLoading =false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarColor: Colors.transparent),
    );
return_isLoading
        ? Scaffold(
      body: Container(
        child: Center(
          child: CircularProgressIndicator(),
        ),
      ),
    )
        : recentExam.results.length == 0

        ? Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text(
            '재생할 피드백 영상이 없습니다',
            style: TextStyle(
                fontSize: 18.sp, fontWeight: FontWeight.bold),
          ),
          Text(
            '기억도 체크를 진행하고',
            style: TextStyle(
                fontSize: 18.sp, fontWeight: FontWeight.bold),
          ),
          Text(
            '나만의 피드백 영상을 받아보세요',
            style: TextStyle(
                fontSize: 18.sp, fontWeight: FontWeight.bold),
          ),
          Container(
            height: 10,
          ),
          InkWell(
            onTap: () {},
            child: Container(
              padding: EdgeInsets.only(
                  top: 5, bottom: 5, left: 10, right: 10),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(10.0),
                color: mainThemeColor(),
              ),
              child: Padding(
                padding:constEdgeInsets.symmetric(
                    horizontal: 15.0, vertical: 8.0),
                child: Text("기억도 체크하기",
                    style: TextStyle(
                        fontSize: 15.sp,
                        color: Colors.black,
                        fontWeight: FontWeight.bold)),
              ),
            ),
          ),
        ],
      ),
    )
//프로바이더 적용
: ChangeNotifierProvider.value(
      value: FeedbackTabProvider(examResult),
      child: Material(
        child: FeedbackTabPlayV(0),
      ),
    );
  }
}

classFeedbackTabPlayVextendsStatefulWidget {
finalint pageInt;

  FeedbackTabPlayV(this.pageInt);

  @override
  _FeedbackTabPlayVState createState() => _FeedbackTabPlayVState();
}

//페넬 현제페이지의 퍼센트계산한다은 실시간으로 바텀네비 줄여주기
finalValueNotifier<double> playerExpandProgress =
ValueNotifier(playerMinHeight);
//
// // ValueNotifier<bool> currentlyPlaying = ValueNotifier(null);
//
constdouble playerMinHeight = 80;
constdouble playerMaxHeight = 370;
constminiplayerPercentageDeclaration = 0.1;

class_FeedbackTabPlayVStateextendsState<FeedbackTabPlayV> {
final_scaffoldKey = GlobalKey<ScaffoldState>();

//child를 리프래시 시키는 int
int _count = 0;

  bool visibility =true;
  int currentIndex = 2;

//사진 이미지 다받아왔는지 확인
bool _isLoading =true;

  double _fabHeight;
  double _panelHeightOpen;
  bool isReady =false;

//블러용
double _sigmaX = 10.0;// from 0-10
double _sigmaY = 10.0;// from 0-10
double _opacity = 0.5;// from 0-1.0

  //
  // //TODO:페넬 닫았을때 높이
double _panelHeightClosed = 11.0.h;
finaldouble _initFabHeight = 0;

//페넬안에 이미지
List<String> providerPanelImages = List<String>();
  List<NetworkImage> thumbnails = List<NetworkImage>();

  @override
voidinitState() {
super.initState();
    Future.delayed(Duration.zero, ()async{
      context.read<FeedbackTabProvider>().init(Provider.of<TabPageProvider>(context, listen:false).counterForFeedback.value);
varfeedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);
//세로 initial page세팅
feedbackModel.setPageInt(widget.pageInt);
    });
    _fabHeight = _initFabHeight;

    currentVisibility.addListener(() {
      visibility = currentVisibility.visibility.value;
    });
  }

  @override
voiddispose() {
super.dispose();
// _tabController.dispose();
}

void_buildThumbnailImages() {
// Thumbnail이미지 미리 생성
varfeedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);
if(feedbackModel.panelImageForPanel.length == providerPanelImages.length)return;
    providerPanelImages = List.from(feedbackModel.panelImageForPanel);

    List<bool> isThumbnailLoaded = List.filled(providerPanelImages.length,false);
    providerPanelImages.asMap().forEach((idx, element) {
varni = NetworkImage(element);
      ni.resolve(fp.ImageConfiguration())
          .addListener(ImageStreamListener(
              (info, call) {
            isThumbnailLoaded[idx] =true;

//전체 다 확인 후 로딩 완료되었다면, _isLoading = true;
if(isThumbnailLoaded.contains(false))return;

            setState(() {
              _isLoading =false;
            });
          }));
      thumbnails.add(ni);
    });
  }

  @override
  Widget build(BuildContext context) {
    _panelHeightOpen = MediaQuery.of(context).size.height * .80;
    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarColor: Colors.transparent),
    );
    _buildThumbnailImages();
finalfeedbackModel = Provider.of<FeedbackTabProvider>(context);
returnMaterial(
// child:
child: _isLoading || (// Loading은 thumbnail이미지 로딩까지 완료된 후에 true
!feedbackModel.initReady &&
              feedbackModel.playList.isNotEmpty)
          ? Container(
          child: Center(
            child: CircularProgressIndicator(),
          ))
//페넹 붙이기
: SlidingUpPanel(
        controller: Provider.of<FeedbackTabProvider>(context).panelController,
        maxHeight: 97.0.h,
        minHeight: feedbackModel.visibility ? _panelHeightClosed : 0,
//배경색
// color: playerExpandProgress.value < 81.0 ? Colors.transparent : Colors.white,
        // color: Colors.black.withOpacity(_opacity),
color: Colors.transparent,
        backdropEnabled:true,
        backdropColor: Colors.transparent,
        backdropTapClosesPanel:true,
        parallaxEnabled:false,
// parallaxOffset: .5,
boxShadow: <BoxShadow>[
          BoxShadow(
            blurRadius: 0,
            color: Colors.transparent,
          )
        ],
        body: feedbackModel.playList.isEmpty
            ? Container(
          color: Colors.black,
        )
            : _body(),
        panelBuilder: (sc) => _panel(sc),
        borderRadius: playerExpandProgress.value > 30.0
            ? BorderRadius.only(
            topLeft: Radius.circular(20),
            topRight: Radius.circular(20))
            : BorderRadius.only(),
        onPanelSlide: (double pos) => setState(
              () {
            playerExpandProgress.value =
                pos * (97.0.h - _panelHeightClosed) + _initFabHeight;
          },
        ),
      ),
    );
  }

  Widget _panel(ScrollController sc) {
finalfeedbackModel = Provider.of<FeedbackTabProvider>(context);
returnfeedbackModel.initReady ==false
? Container(
      child: Center(
        child: CircularProgressIndicator(),
      ),
    )
        : AnimatedSwitcher(
      duration: Duration(milliseconds: 10),
      reverseDuration: Duration(milliseconds: 10),
      transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
      },
      child: Container(
        key: ValueKey(playerExpandProgress.value),
        child: playerExpandProgress.value > 80.0
            ? BackdropFilter(
          filter:
          ImageFilter.blur(sigmaX: _sigmaX, sigmaY: _sigmaY),
          child: Container(
            color: Colors.black.withOpacity(_opacity),
            child: ListView(
              physics: ClampingScrollPhysics(),
              controller: sc,
              children: <Widget>[
                SizedBox(
                  height: 12.0,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      width: 30,
                      height: 5,
                      decoration: playerExpandProgress.value > 81.0
                          ? BoxDecoration(
                          color: Colors.black.withOpacity(0.1),
// color: Colors.grey[300],
borderRadius: BorderRadius.all(
                              Radius.circular(12.0)))
                          : BoxDecoration(),
                    ),
                  ],
                ),
                InkWell(
                  onTap: () {
                    feedbackModel.panelController
                        .animatePanelToPosition(0,
                        duration: Duration(milliseconds: 300),
                        curve: Curves.easeInCirc);
                    feedbackModel.setPanelOpen(false);
                  },
                  child: SizedBox(
                    height: 15.0,
                  ),
                ),
                InkWell(
                  onTap: () {
                    feedbackModel.panelController
                        .animatePanelToPosition(0,
                        duration: Duration(milliseconds: 300),
                        curve: Curves.easeInCirc);
                    feedbackModel.setPanelOpen(false);
                  },
                  child: Container(
                    padding: EdgeInsets.symmetric(
                        horizontal: 20.0, vertical: 10.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
// Text(
                        //   "챕터 ${widget._examResult.exam.chapter}피드백 목록",
                        //   style: baseTextBStyle().copyWith(fontSize: 20.sp),
                        // ),
Text(
                          "총 ${feedbackModel.playList.length}단어",
// '$playerExpandProgress , $_panelHeightClosed',
style: regularTextStyle()
                              .copyWith(color: Colors.white),
                        ),
                      ],
                    ),
                  ),
                ),
                Column(
                  children: [

//묶는거 보류
ListView.builder(
                      shrinkWrap:true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: feedbackModel.playList.length,
                      itemBuilder: (BuildContext context, int index) {
returnColumn(
                          children: [
//만약 첫번째 index이고 미시청이거나 미시청이고 전꺼랑 챕터가 같지 않으면
if(index == 0 && !feedbackModel.playList[index].last.viewed
                                || !feedbackModel.playList[index].last.viewed
                                    && feedbackModel.playList[index].last.relatedExam.chapter != feedbackModel.playList[index - 1].last.relatedExam.chapter
                            )
                              Column(
                                children: [
                                  Text('미시청 영상',
                                    style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.bold, color: Colors.grey[500]),
                                  ),
                                  Text('${feedbackModel.playList[index].last.relatedExam.chapter}챕터',
                                    style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.bold, color: Colors.grey[500]),
                                  ),
                                ],
                              ),
//만약 첫번째 index이고 시청이거나 시청이고 전꺼랑 같지않으면
if(index == 0 && feedbackModel.playList[index].last.viewed
                                || feedbackModel.playList[index].last.viewed
                                    && feedbackModel.playList[index].last.relatedExam.chapter != feedbackModel.playList[index - 1].last.relatedExam.chapter)
                              Text('${feedbackModel.playList[index].last.relatedExam.chapter}챕터',
                                style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.bold, color: Colors.grey[500]),
                              ),

                        InkWell(
                            onTap: () {
// feedbackModel.panelController.close();
currentVisibility.setVisibility(false);
                              feedbackModel.setplayListUnviewd2(index);
// if(!feedbackModel.playList[index].last.viewed){
                              //
                              // } else {
                              //   feedbackModel.setJumpPage(index);
                              // _key.currentState.dispose();
                              // _key.currentState.;
if(mounted)// await과 setState()의 사이..
setState(() => ++_count);

                              feedbackModel.setJumpPage(index);
                              feedbackModel.setPanelOpen(false);
// feedbackModel.setJumpPage(index);
},
                            child: _buildWordItem(
                                feedbackModel.playList[index],
                              index,
                            ),
                          ),

                          ],
                        );
                      }
                    ),
                  ],

                ),
                SizedBox(
                  height: 24,
                ),
              ],
            ),

          ),
        )
            : feedbackModel.visibility
            ? BackdropFilter(
          filter: ImageFilter.blur(
              sigmaX: _sigmaX, sigmaY: _sigmaY),
          child: Container(
            color: Colors.black.withOpacity(_opacity),
// width: 100.0.w,
child: Container(
// height: 9.0.h,
              // color: Colors.red,
child: Column(
                children: [
                  Padding(
                    padding:constEdgeInsets.only(top: 8.0),
                    child: Row(
                      mainAxisAlignment:
                      MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
                        IconButton(
                          onPressed: () {
                            feedbackModel.setSaved(
                                feedbackModel
                                    .currentFeedback.id,
                                feedbackModel
                                    .currentFeedback.saved);
if(feedbackModel.favorate) {
                              feedbackModel
                                  .setFavorate(false);
                              _scaffoldKey.currentState
                                  .showSnackBar(CustomMessage
                                  .displaySnackBar(
                                  '즐겨찾기에서 해제되었습니다'));
                            }else{
                              feedbackModel.setFavorate(true);
                              _scaffoldKey.currentState
                                  .showSnackBar(CustomMessage
                                  .displaySnackBar(
                                  '즐겨찾기에 등록이 되었습니다'));
                            }
                          },
                          padding: EdgeInsets.symmetric(
                              horizontal: 5.0.w, vertical: 5),
                          icon: Icon(
                            feedbackModel.favorate
                                ? Icons.star_rounded
: Icons.star_border_rounded,
                            size: 5.0.h,
                            color: Colors.white,
                          ),
                        ),
                        Container(
                          width: 3.0.w,
                        ),
                        InkWell(
                          onTap: () {
                            feedbackModel.panelController
                                .animatePanelToPosition(1,
                                duration: Duration(
                                    milliseconds: 400),
                                curve:
                                Curves.easeOutCirc);
                            feedbackModel.setPanelOpen(true);
                          },
                          child: Column(
                            mainAxisAlignment:
                            MainAxisAlignment.center,
                            crossAxisAlignment:
                            CrossAxisAlignment.start,
                            children: [
                              Text(
                                feedbackModel.playList.isEmpty
                                    ? ""
// : "${feedbackModel.playListReversed[widget.verticalPageIndex][widget.horizontalpageIndex].feedback.vocabulary.word}",
: "${feedbackModel.currentFeedbackPlaylist.feedback.vocabulary.word}",
                                style: headerTextStyle()
                                    .copyWith(
                                    color: Colors.white),
                              ),
                              Text(
                                feedbackModel.playList.isEmpty
                                    ? ""
// : "${widget.horizontalpageIndex + 1}단계 피드백",
: "${feedbackModel.rowIndex + 1}단계 피드백",
                                style: baseTextStyle()
                                    .copyWith(
                                    color: Colors.white,
                                    fontSize: 11.0.sp),
                              ),
                            ],
                          ),
                        ),
                        Expanded(
                          child: InkWell(
                              onTap: () {
                                feedbackModel.panelController
                                    .animatePanelToPosition(1,
                                    duration: Duration(
                                        milliseconds:
                                        400),
                                    curve: Curves
                                        .easeOutCirc);
                                feedbackModel
                                    .setPanelOpen(true);
                              },
                              child: Container()),
                        ),
                        Padding(
                          padding:constEdgeInsets.symmetric(
                              horizontal: 10.0),
                          child: Container(
                            height: 8.0.h,
                            width: 15.0.w,
                            decoration: BoxDecoration(
                              color: Colors.black
.withOpacity(0.1),
                              borderRadius: BorderRadius.all(
                                  Radius.circular(12.0)),
                            ),
                            child: IconButton(
                              onPressed: () {
if(feedbackModel.loop) {
                                  feedbackModel
                                      .setLoop(false);
                                }else{
                                  feedbackModel.setLoop(true);
                                }
// feedbackModel._loop = feedbackModel.loop;
print(
                                    'loop loop loop loop loop  ${feedbackModel.loop}');
// setState(() {
                                //   loop = !loop;
                                //   _controller.setLooping(loop);
                                // });
},
                              icon: Icon(
                                feedbackModel.loop
                                    ? Icons.repeat_one
: Icons.repeat,
// Icons.repeat,
size: 25.0.sp,
                                color: Colors.white,
                              ),
                            ),
                          ),
                        ),
                        Container(
                          height: 8.0.h,
                          width: 15.0.w,
                          decoration: BoxDecoration(
                            color:
                            Colors.black.withOpacity(0.1),
                            borderRadius: BorderRadius.all(
                                Radius.circular(12.0)),
                          ),
                          child: IconButton(
                            onPressed: () {
                              feedbackModel.panelController
                                  .animatePanelToPosition(1,
                                  duration: Duration(
                                      milliseconds: 400),
                                  curve:
                                  Curves.easeOutCirc);
                              feedbackModel
                                  .setPanelOpen(true);
                            },
                            icon: Icon(
                              Icons.playlist_play,
                              size: 25.0.sp,
                              color: Colors.white,
                            ),
                          ),
                        ),
                        Container(
                          width: 2.0.w,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        )
            : Container(),
      ),
    );
  }

//페넬안에 플레이리스트 카드 한개한개
Container _buildWordItem(List<feedbacks.Results> voca, int index) {
finalfeedbackModel = Provider.of<FeedbackTabProvider>(context);
returnContainer(
      child: Column(
        children: [
          Container(
            color: Colors.white.withOpacity(0.2),
            padding: EdgeInsets.only(left: 20, right: 20, top: 10, bottom: 10),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.all(
                        Radius.circular(10),
                      ),
                      child: Container(
                          width: 55.w,
                          height: 55.h,
                          decoration: BoxDecoration(
                            image: DecorationImage(
                              image: thumbnails[index],//미리 로딩된 것을 사용.
fit: BoxFit.cover,
                            ),
                          ),
                          child: Stack(
                            children: [
                              Visibility(
                                visible:
                                feedbackModel.playList[index].last.viewed,
                                child: Positioned(
                                  bottom: 0,
                                  child: Container(
                                    alignment: Alignment.center,
                                    width: 55.w / 3 * 2,
                                    height: 55.h * 0.23,
                                    color: Colors.black.withOpacity(0.6),
                                    child: Text(
                                      "학습완료",
                                      style: baseTextStyle().copyWith(
                                          color: Colors.white, fontSize: 8.sp),
                                    ),
                                  ),
                                ),
                              ),
                              Visibility(
                                visible: feedbackModel.currentFeedbackPlaylist.feedback.vocabulary.word == voca.last.feedback.vocabulary.word ?true:false,
                                child: Center(
                                            child: Lottie.asset(
                                                "assets/play_button.json",
                                                width: 80,
                                                repeat:true,
                                                fit: BoxFit.cover),
// Icon(
                                            //   Icons.play_circle_fill,
                                            //   color: Colors.red,
                                            //   size: 10.0.w,
                                            // ),
),
                              ),
// ValueListenableBuilder<int>(
                              //     valueListenable: feedbackModel.counterInt,
                              //     builder: (context, int value, child) {
                              //       return Visibility(
                              //         visible: value == index ? true : false,
                              //         child: Center(
                              //           child: Lottie.asset(
                              //               "assets/play_button.json",
                              //               width: 80,
                              //               repeat: true,
                              //               fit: BoxFit.cover),
                              //           // Icon(
                              //           //   Icons.play_circle_fill,
                              //           //   color: Colors.red,
                              //           //   size: 10.0.w,
                              //           // ),
                              //         ),
                              //       );
                              //     }),
],
                          )),
                    ),
                  ],
                ),
                Padding(padding: EdgeInsets.only(left: 10)),
// Expanded(
Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Text(
                      voca.last.feedback.vocabulary.word,
                      style:
                      TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                      maxLines: 1,
                      overflow: TextOverflow.fade,
                    ),
                    Text(
                      "${voca.last.feedback.level}번째 피드백",
                      style: TextStyle(
                          fontSize: 15, color: Colors.white.withOpacity(0.5)),
                    ),
                  ],
                ),
              ],
            ),
          ),
          Container(
            height: 0.2,
            color: Colors.white.withOpacity(0.5),
          ),
        ],
      ),
    );
  }

//세로 가로 비디오플레이로 넘어감
Widget _body() {
returnFeedbackTabPreload(
//key값으로 리프레쉬
key: ValueKey<int>(_count),
    );
  }
}

FeedbackTabPreload

import'dart:async';
import'dart:math';
import'package:like_button/like_button.dart';
import'package:line_awesome_flutter/line_awesome_flutter.dart';
import'package:lottie/lottie.dart';
import'package:mccounting_text/mccounting_text.dart';
import'package:provider/provider.dart';
import'package:quickcheck/model/user.dart';
import'package:quickcheck/utils/ApiAdapter.dart';
import'package:quickcheck/utils/shared_prefs.dart';
import'package:quickcheck/utils/show_message.dart';
import'package:quickcheck/view/Common/tab_page.dart';
import'package:quickcheck/view/Common/tab_page_provider.dart';
import'package:quickcheck/view/TestTab/feedback_result.dart';
import'package:quickcheck/view/feedback_tab/feedback_tab_play.dart';
import'package:quickcheck/view/feedback_tab/feedback_tab_provider.dart';
import'package:smooth_page_indicator/smooth_page_indicator.dart';
import'package:video_player/video_player.dart';
import'package:flutter/material.dart';
import'package:preload_page_view/preload_page_view.dart';
import'package:quickcheck/style.dart';
import'package:flutter_screenutil/flutter_screenutil.dart';
import'package:flutter/services.dart';
import'package:quickcheck/model/feedbacks.dart'asfeedbacks;
import'package:sizer/sizer.dart';
// import 'package:scrolling_page_indicator/scrolling_page_indicator.dart';

classFeedbackTabPreloadextendsStatefulWidget {
constFeedbackTabPreload({Key key}) :super(key: key);

  @override
  FeedbackTabPreloadState createState() => FeedbackTabPreloadState();
}

classFeedbackTabPreloadStateextendsState<FeedbackTabPreload>withTickerProviderStateMixin {
//스넥바용
final_scaffoldKey = GlobalKey<ScaffoldState>();

//세로 페이지가 완전히 바뀌고나서 저장되는 값
int currentVertical = 0;
  double currentVerticalPageDouble = 0;
  double currentHorizontalPageDouble = 0;

//현제 세로페이지가 움직이는 상테인지
bool verticalIsOnPageTurning =false;
  bool verticalVisibility =true;

// ScrollPhysics verticalPreloadPhysics = new NeverScrollableScrollPhysics();

voidinitController() {
// FeedbackProvider feedbackModel =
    // Provider.of<FeedbackProvider>(context, listen: false);
FeedbackTabProvider feedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);

varscrollListener;
    scrollListener = () {
// print("scrollListener - ${feedbackModel.pageControllerMain.page},${feedbackModel.pageControllerMain.position}");
      /////////////////////////////////////////////
      // horizontal blocking when loading is not done
      /////////////////////////////////////////////
Future.delayed(Duration.zero, ()async{
        setState(() {
          currentVerticalPageDouble = feedbackModel.pageControllerMain.page;
        });
      });
// setState(() {
      //   currentDouble = feedbackModel.pageControllerMain.page;
      // });

      // called after image loading.
varcvIdx = feedbackModel.pageControllerMain.page.round();
varchIdx = currentHorizontalPageDouble.round();
// var vMax = feedbackModel.playListReversed.length;
varvMax = feedbackModel.playListUnviewd.keys.length;
// var hMax = feedbackModel.playListReversed[cvIdx].length;

      //현재 보고 있는 페이지를 기준으로 업데이트.
      //어디로 로딩할지 모르기 때문에,상하좌우 전부 검사하여 하나라도 false이면 못움직이게 막음.
      // min(), max()는 boundry check용
varup = feedbackModel.thumbnailLoadingIsDone[max(0, cvIdx - 1)][chIdx];
vardown = feedbackModel.thumbnailLoadingIsDone[min(vMax - 1, cvIdx + 1)][chIdx];

// print("ImageStreamListener - ${cvIdx},${vMax},${chIdx},${hMax}, ${up},${down},${right},${left}");
if((!(up[0] && up[1]) && feedbackModel.pageControllerMain.page < feedbackModel.pageControllerMain.page.round()) ||
          (!(down[0] && down[1]) && feedbackModel.pageControllerMain.page > feedbackModel.pageControllerMain.page.round())) {
//위가 아직 로딩되지 않았는데 올라가려고 하는 경우,혹은 아래가 아직 로딩되지 않았는데 내려가려고 하느 경우.
        //TODO:안넘어가는 조건부분 :로딩바 넣어주세요.
feedbackModel.pageControllerMain.jumpToPage(cvIdx.toInt());
      }

if(verticalIsOnPageTurning &&
          feedbackModel.pageControllerMain.page == feedbackModel.pageControllerMain.page.roundToDouble()) {
        print('11111111111111');
        feedbackModel.setPageMoving(false);
// print('움직인다 움직인다 움직인다 1111111');
setState(() {
          currentVertical = feedbackModel.pageControllerMain.page.toInt();
          verticalIsOnPageTurning =false;
        });
      }else if(!verticalIsOnPageTurning && currentVertical.toDouble() != feedbackModel.pageControllerMain.page) {
        feedbackModel.setPageMoving(true);
// print('움직인다 움직인다 움직인다 3333333');
        //포인트 올라간거 확인하고 포인트 맞춰주는 곳
if(feedbackModel.userPointRecord != feedbackModel.userPoint.value){
          feedbackModel.setPointRecord(feedbackModel.userPoint.value);
        }
//움직일때 프로그래시브바 숨겨두기
if((currentVertical.toDouble() - feedbackModel.pageControllerMain.page).abs() < 0.002) {
          print('3333333');
          feedbackModel.setPageMoving(false);
        }
// print('움직인다 움직인다 움직인다 22222');
        // print('움직인다 움직인다 움직인다 ${(current.toDouble() - feedbackModel.pageControllerMain.page).abs()}');
if((currentVertical.toDouble() - feedbackModel.pageControllerMain.page).abs() > 0.8) {
// print('움직인다 움직인다 움직인다 3333333');
setState(() {
            verticalIsOnPageTurning =true;
          });
// _scaffoldKey.currentState.removeCurrentSnackBar();
}
      }
    };
    feedbackModel.pageControllerMain.addListener(scrollListener);
  }

  @override
voidinitState() {
super.initState();
    initController();
  }

  @override
voiddispose() {
// initController();
super.dispose();
  }

  @override
  Widget build(BuildContext context) {
// FeedbackProvider feedbackModel =
    // Provider.of<FeedbackProvider>(context, listen: false);
FeedbackTabProvider feedbackModel = Provider.of<FeedbackTabProvider>(context);
returnScaffold(
      key: _scaffoldKey,
      body: Builder(builder: (BuildContext context) {
returnStack(
          alignment: Alignment.center,
          children: [
            Container(
                height: MediaQuery.of(context).size.height,
                color: Colors.black,
                child: PreloadPageView.builder(
                  controller: feedbackModel.pageControllerMain,
                  scrollDirection: Axis.vertical,
                  itemCount: feedbackModel.playListUnviewd.keys.length,
// preloadPagesCount: feedbackModel.playListReversed.length,
preloadPagesCount: 3,
// physics: verticalPreloadPhysics,
itemBuilder: (context, verticalPageIndex) {
returnContainer(
                      child: PageHorizontal(
                          verticalPageIndex: verticalPageIndex,
                          currentVertical: currentVertical,
                          currentVerticalPageDouble: currentVerticalPageDouble,
                          verticalIsOnPageTurning: verticalIsOnPageTurning,
                          setVerticalVisibility: (bool setVisibility){
if(setVisibility != verticalVisibility){
                              setState(() {
                                verticalVisibility = setVisibility;
                              });
                            }
                          },
                          setCurrentHorizontalPageDouble: (double val) {
if(currentHorizontalPageDouble != val) {
                              setState(() {
                                currentHorizontalPageDouble = val;
                              });
                            }
                          }
                      ),
                    );
                  },
                  onPageChanged: (pageIndex) {
                    feedbackModel.setColindexRowIndex(colIndexP: pageIndex);
                    currentVertical = feedbackModel.pageControllerMain.page.toInt();
                    verticalIsOnPageTurning =false;
if(pageIndex == feedbackModel.playList.length) {
                      _scaffoldKey.currentState.showSnackBar(
                          CustomMessage.displaySnackBar(
                              '마지막 단어의 동영상 입니다'));
                    }
                  },
                )),

//스크롤해도 안움직이는 영상들
Positioned(
              top: 3.0.h,
              right: 5.0.w,
              child: feedbackModel.visibility
                  ? Container(
                padding: EdgeInsets.only(
                    left: 5, right: 5, top: 5, bottom: 5),
                decoration: BoxDecoration(
                  color: Colors.white.withOpacity(0.5),
                  borderRadius: BorderRadius.circular(30),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment:
                  CrossAxisAlignment.center,
                  children: [
                    Container(
                      child: Image.asset(
                        'assets/coin.png',
                        width: 20,
                      ),
                      margin: EdgeInsets.only(right: 5),
                    ),// fit: BoxFit.cover,
feedbackModel.userPoint !=null
? ValueListenableBuilder(
                      valueListenable:
                      feedbackModel.userPoint,
                      builder:
                          (context, int value, child) {
returnRow(
                          children: [
                            McCountingText(
                              begin: feedbackModel
                                  .userPointRecord
                                  .toDouble(),
                              end: value.toDouble(),
                              style: baseTextStyle()
                                  .copyWith(
                                fontSize: 11.0.sp,
                                fontWeight:
                                FontWeight.bold,
                              ),
                              duration:
                              Duration(seconds: 1),
                              curve: Curves.decelerate,
                            ),
                            Text(
                              'P',
                              style: baseTextStyle()
                                  .copyWith(
                                fontSize: 11.0.sp,
                                fontWeight:
                                FontWeight.bold,
                              ),
                            ),
                          ],
                        );
                      },
                    )
                        : Text(
                      '0P  ',
                      style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 11.0.sp),
                    ),
// feedbackModel.userPoint != null ? Text('${feedbackModel.userPoint.value}P  ', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 11.0.sp),
                    // )  : Text('0P  ', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 11.0.sp),),
],
                ),
              )
                  : Container(),
            ),
//포인트 없어졌다 나타내기
if(feedbackModel.showPluse.value)
              Positioned(
                right: 5.0.w,
                top: 9.0.h,
                child: AnimatedSwitcher(
                  duration: Duration(milliseconds: 50),
                  reverseDuration: Duration(milliseconds: 200),
                  transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
                  },
                  child: Container(
                    key: ValueKey(feedbackModel.visibility),
                    child: feedbackModel.visibility
                        ? Container(
                      height: 4.0.h,
                      width: 14.0.w,
                      decoration: BoxDecoration(
                        color: Colors.yellow.withOpacity(0.7),
// color: Colors.white.withOpacity(0.5),
borderRadius: BorderRadius.circular(30),
                      ),
                      child: Center(
                          child: Text(
                            '+ 5P',
                            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 11.0.sp, color: Colors.white),
                          )),
                    )
                        : Container(),
                  ),
                ),
              ),

//점박이
Positioned(
              left: 5.0.w,
              child: feedbackModel.visibility
                  ? Container(
                child: SmoothPageIndicator(
// preloadController: feedbackModel.pageControllerMain,
controller: feedbackModel.pageControllerMain,
                  count: feedbackModel.playListUnviewd.keys.length,
                  axisDirection: Axis.vertical,
                  effect:ScrollingDotsEffect(
                    maxVisibleDots: 5,
                    spacing: 7.0,
                    radius: 30.0,
                    dotWidth: 15.0,
                    dotHeight: 5.0,
                    dotColor: Colors.black.withOpacity(0.2),
// fixedCenter: true,
                    // paintStyle: PaintingStyle.stroke,
strokeWidth: 0,
                    activeDotColor: Color(0xffbfff00),
                  ),
                ),
              )
                  : Container(),
            ),

          ],
        );
      },
      ),
    );
  }

}

classPageHorizontalextendsStatefulWidget {
  PageHorizontal({
this.verticalPageIndex,
this.currentVertical,
this.currentVerticalPageDouble,
this.verticalIsOnPageTurning,
this.currentHorizontalPageIndex,
this.isPaused,
this.setVerticalVisibility,
this.setCurrentHorizontalPageDouble
  });

finalint verticalPageIndex;
finalint currentVertical;
finaldouble currentVerticalPageDouble;
finalbool verticalIsOnPageTurning;
finalint currentHorizontalPageIndex;
finalbool isPaused;
finalFunction(bool) setVerticalVisibility;
finalFunction(double) setCurrentHorizontalPageDouble;

  @override
  _PageHorizontalState createState() => _PageHorizontalState();
}

class_PageHorizontalStateextendsState<PageHorizontal> {
  double currentHoriDouble = 0;
  int currentHorizontal = 0;
  bool horizontalIsOnPageTurning =false;

// final _scaffoldKey = GlobalKey<ScaffoldState>();
PreloadPageController pageControllerHori;

// ScrollPhysics horizontalPreloadPhysics = new NeverScrollableScrollPhysics();

voidinitController2() {
// FeedbackProvider feedbackModel =
    // Provider.of<FeedbackProvider>(context, listen: false);
FeedbackTabProvider feedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);
    pageControllerHori =
// new PreloadPageController(initialPage: feedbackModel.playListReversed[widget.verticalPageIndex].length - 1);
newPreloadPageController(initialPage: feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length - 1);
    setState(() {
// currentHorizontal = feedbackModel.playListReversed[widget.verticalPageIndex].length - 1;
currentHorizontal = feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length - 1;
    });

varscrollListenerHori;
    scrollListenerHori = () {
// print("scrollListenerHori - ${pageControllerHori.page},${pageControllerHori.position}");

      /////////////////////////////////////////////
      // horizontal blocking when loading is not done
      /////////////////////////////////////////////
setState(() {
        currentHoriDouble = pageControllerHori.page;
      });

// called after image loading.
varcvIdx = widget.currentVerticalPageDouble.round();
varchIdx = pageControllerHori.page.round();
// var hMax = feedbackModel.playListReversed[cvIdx].length;
varhMax = feedbackModel.playListUnviewd.values.elementAt(cvIdx).length;

//현재 보고 있는 페이지를 기준으로 업데이트.
      //어디로 로딩할지 모르기 때문에,상하좌우 전부 검사하여 하나라도 false이면 못움직이게 막음.
      // min(), max()는 boundry check용
varright = feedbackModel.thumbnailLoadingIsDone[cvIdx][min(hMax - 1, chIdx + 1)];
varleft = feedbackModel.thumbnailLoadingIsDone[cvIdx][max(0, chIdx - 1)];

// print("ImageStreamListener - ${cvIdx},${vMax},${chIdx},${hMax}, ${up},${down},${right},${left}");
if((!(right[0] && right[1]) && pageControllerHori.page > pageControllerHori.page.round()) ||
          (!(left[0] && left[1]) && pageControllerHori.page < pageControllerHori.page.round())) {
//우측이 아직 로딩되지 않았는데 가려고 하는 경우,혹은 좌측이 아직 로딩되지 않았는데 가려고 하느 경우.
        //TODO:안넘어가는 조건부분 :로딩바 넣어주세요.
pageControllerHori.jumpToPage(chIdx.toInt());
      }

if(horizontalIsOnPageTurning && pageControllerHori.page == pageControllerHori.page.roundToDouble()) {

        setState(() {
          currentHorizontal = pageControllerHori.page.toInt();
          horizontalIsOnPageTurning =false;
        });
      }else if(!horizontalIsOnPageTurning && currentHorizontal.toDouble() != pageControllerHori.page) {
if((currentHorizontal.toDouble() - pageControllerHori.page).abs() > 0.7) {

          setState(() {
            horizontalIsOnPageTurning =true;
          });
        }
      }
    };

    pageControllerHori.addListener(scrollListenerHori);
  }

  @override
voidinitState() {
super.initState();
    initController2();
  }

  @override
voiddispose() {
// initController2();
super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    FeedbackTabProvider feedbackModel = Provider.of<FeedbackTabProvider>(context);
if(widget.verticalIsOnPageTurning && currentHorizontal != feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length - 1) {
      pageControllerHori.animateToPage(
        feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length - 1,
        duration: Duration(milliseconds: 300),
// curve: Curves.linear,
curve: Curves.linear,
      );
    }

returnPreloadPageView.builder(
      controller: pageControllerHori,
      scrollDirection: Axis.horizontal,
// itemCount: feedbackModel.playList[widget.verticalPageIndex].length,
itemCount: feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length,
      preloadPagesCount: feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length,
// physics: horizontalPreloadPhysics,

      // preloadPagesCount: 2,
itemBuilder: (context, horizontalPageIndex) {
returnContainer(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          color: Colors.black,
          child: VideoApp(
// url: feedbackModel.playListReversed[widget.verticalPageIndex][pageIndexHori].feedback.url,
verticalPageIndex: widget.verticalPageIndex,
            horizontalpageIndex: horizontalPageIndex,
            currentVertical: widget.currentVertical,
            currentHorizontal: currentHorizontal,
            currentVerticalPageDouble: widget.currentVerticalPageDouble,
            currentHoriDouble: currentHoriDouble,
            verticalIsOnPageTurning: widget.verticalIsOnPageTurning,
            horizontalIsOnPageTurning: horizontalIsOnPageTurning,
            onButtonTapped: (int i) {
              pageControllerHori.animateToPage(
                i,
                duration: Duration(milliseconds: 300),
                curve: Curves.linear,
// curve: Curves.fastOutSlowIn,
);
            },
            resultFeedback: feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex)[horizontalPageIndex],
            setVerticalVisibility: (bool setVerticalVisibility) {
              widget.setVerticalVisibility(setVerticalVisibility);
            },
          ),
        );
      },
      onPageChanged: (pageIndexHori){
        print('change change1');
        feedbackModel.setColindexRowIndex(rowIndexP: pageIndexHori);
        currentHorizontal = pageControllerHori.page.toInt();
// feedbackModel.rowIndex = pageIndexHori;
print('change change1 ${feedbackModel.rowIndex}');

      },
    );
  }
}

classVideoAppextendsStatefulWidget {
  VideoApp({
// this.url,
this.verticalPageIndex,
this.horizontalpageIndex,
this.currentVertical,
this.currentHorizontal,
this.verticalIsOnPageTurning,
this.horizontalIsOnPageTurning,
this.onButtonTapped,
this.resultFeedback,
this.setVerticalVisibility,
this.currentVerticalPageDouble,
this.currentHoriDouble
  });

// final String url;
finalint verticalPageIndex;
finalint horizontalpageIndex;
finalint currentVertical;
finalint currentHorizontal;
finalbool verticalIsOnPageTurning;
finalbool horizontalIsOnPageTurning;
finalFunction(int) onButtonTapped;
finalfeedbacks.Results resultFeedback;
finalFunction(bool) setVerticalVisibility;
finaldouble currentVerticalPageDouble;
finaldouble currentHoriDouble;

  @override
  _VideoAppState createState() => _VideoAppState();
}

classVideoAppProgressIndicatorController {
voidFunction() adjust = () {};
voidFunction() play = () {};
voidFunction() stop = () {};
}

classVideoAppProgressIndicatorextendsStatefulWidget {
// VideoApp에서 사용하는 VideoProgressIndicator
  // 1초마다 끊키는 것을

VideoAppProgressIndicator({
this.vapiController,
this.controller,
this.dur
  });

finalVideoAppProgressIndicatorController vapiController;
finalVideoPlayerController controller;// pos, dur읽기 위한 controller
finalint dur;// duration in videocontroller

@override
  _VideoAppProgressIndicatorState createState() => _VideoAppProgressIndicatorState();
}

class_VideoAppProgressIndicatorState
extendsState<VideoAppProgressIndicator>withSingleTickerProviderStateMixin {
// VideoAppProgressIndicator를 위한 State
varvideoPlayerControllerListener;
  AnimationController controller;
  int progress;

//최초 시작, pagemove로 인해 재시작,빨리감기/뒤로감기 클릭시
voidadjustProgress() {
    int pos = widget.controller.value.position.inMilliseconds;// current
controller.value = pos.toDouble() / widget.dur.toDouble();//조정
progress = pos;
  }

// play button
voidplay() {
    controller.forward();
  }

// stop button
voidstop() {
    controller.stop();
  }

  @override
voidinitState() {
super.initState();

// controller method
widget.vapiController.adjust = adjustProgress;
    widget.vapiController.play = play;
    widget.vapiController.stop = stop;

// init
progress = 0;
    controller = AnimationController(
        vsync:this,
        duration: Duration(milliseconds: widget.dur));
    controller.stop();
// controller.value =

    // listener를 통해 controller를 조정 변경.
videoPlayerControllerListener = () {
      int pos = widget.controller.value.position.inMilliseconds;// current

      //최신 progress갱신
progress = pos;

//재생되고 있는 상태:
      //그 외에는 속도를 항상 재조정.
if(widget.dur - pos > 1000) {
// 1000초 이내일 경우에는 이 조정을 실시하지 않음.
        // animation이 종료되지 않았는데 pos이 reset되어 돌아오는 경우가 있음.
        //이를 방지하기 위함.
controller.animateTo(1,
            duration: Duration(milliseconds: widget.dur - pos))
            .whenComplete(() {
          controller.reset();//리셋
//끝나면 자동으로 다시 재생.
if(widget.controller.value.isLooping) controller.forward();
        });
      }
    };
    widget.controller.addListener(videoPlayerControllerListener);
  }

  @override
voiddispose() {
    widget.controller.removeListener(videoPlayerControllerListener);
    controller.dispose();
super.dispose();
  }

  @override
  Widget build(BuildContext context) {
varprogressLayout = LayoutBuilder(
        builder: (context, constraints) {
returnAnimatedBuilder(
            animation: controller,
            child: Container(
              width: constraints.maxWidth,
              height: double.infinity,
              color: Colors.white,
            ),
            builder: (context, child) {
// only scale x
              // print("builder - ${controller.value}, ${constraints.maxWidth}");
returnTransform(
                  transform: Matrix4.diagonal3Values(controller.value, 1.0, 1.0),
                  child: child);
            },
          );
        }
    );

varcontainer = Container(
        width: double.infinity,
        height: 5.0.h,
        alignment: Alignment.centerLeft,
        color: Colors.black.withOpacity(0.2),
        child: progressLayout
    );

returncontainer;
  }
}

class_VideoAppStateextendsState<VideoApp> {

  FeedbackTabProvider feedbackModel;

  List<NetworkImage> thumbnails = [];

  VideoPlayerController _controller;
  bool initialized =false;
// bool favorate = false;
bool liked =false;
// bool loop = true;
final_scaffoldKey = GlobalKey<ScaffoldState>();

  bool showPluse =false;

  int viewedInt = 0;
  int likedInt = 0;

  VideoAppProgressIndicatorController vapiController;

// bool panelOpened = false;
finalValueNotifier<bool> panelOpened = ValueNotifier<bool>(false);

voidinitController() {
    vapiController = VideoAppProgressIndicatorController();

    _controller = VideoPlayerController.network(
      widget.resultFeedback.feedback.url,
    );

    _controller.initialize().then((value) {
      setState(() {
        initialized =true;
if(feedbackModel.loop){
          _controller.setLooping(true);
        }
// _controller.setLooping(true);
        // feedbackModel.loop = true;
        // urlSaved = widget.url;
});

//비디오 로딩 완료 마킹
varvIdx = widget.verticalPageIndex;
varhIdx = widget.horizontalpageIndex;

//내 것을 true로 설정.
      // feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][1] = true;
      // print("thumbnailLoadingIsDone[${vIdx}][${hIdx}] = true");

varplayListener;
      playListener = () {
        int dur = _controller.value.duration.inMilliseconds;
        int pos = _controller.value.position.inMilliseconds;

if(!feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][1]
            && dur > 0 && pos == 0) {
//내 것을 true로 설정.
feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][1] =true;
        }

// if(feedbackModel.panelController.isPanelOpen && !panelOpened){
        //   print('열림 열림 열림 열림 열림 열림 열림 열림 열림 열림 열림 ');
        //   setState(() {
        //     panelOpened = true;
        //   });
        // } else if (feedbackModel.panelController.isPanelClosed && panelOpened){
        //   print('닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 ');
        //   setState(() {
        //     panelOpened = false;
        //   });
        // }

        // NOTE: panelOpened값이 playListener안에 있는것이 어색해서
//    build()로 빼두었습니다.잘못된 것이라면 수정 부탁드립니다(By Kyoseung).

if(dur - pos < 400) {
if(feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex)[widget.horizontalpageIndex].viewed ==false){
            feedbackModel.setShowPluse(true);
            setState(() {
                  showPluse =true;
                  viewedInt += 1;
                });

            feedbackModel.setView(feedbackModel.playListUnviewd.keys.elementAt(widget.verticalPageIndex), widget.horizontalpageIndex, widget.verticalPageIndex);
              ApiAdapter.patchFeedback(widget.resultFeedback.id, viewed:true).then((value) {
if(value == 200){
                  print('ok ok ok ok ok');
                  feedbackModel.setPoint();
                }
              });
// .then((value) {
              // print('ok ok ok ok ok');
              // feedbackModel.setPoint();
print('ok2 ok2 ok2 ok2 ok2');
// Timer(Duration(milliseconds: 500), () {
setState(() {
//바텀네비 숫자제어
Provider.of<TabPageProvider>(context, listen:false).setCounterForFeedback(1);
// feedbackModel.setShowPluse(false);
                // showPluse = false;
print('ok3 ok3 ok3 ok3 ok3');
                feedbackModel.setPointRecord(feedbackModel.userPoint.value);
              });
// });
Timer(Duration(seconds: 2), () {
                feedbackModel.setShowPluse(false);
              });
              print('TabPageProvider TabPageProvider TabPageProvider ${Provider.of<TabPageProvider>(context, listen:false).counterForFeedback.value}');
if(Provider.of<TabPageProvider>(context, listen:false).counterForFeedback.value == 0){
                _showDialog();
              }
          }
// if (feedbackModel.playList[widget.verticalPageIndex][widget.horizontalpageIndex].viewed == false) {
          //   feedbackModel.setShowPluse(true);
          //   setState(() {
          //     showPluse = true;
          //     viewedInt += 1;
          //   });
          //
          //
          //   feedbackModel.setView(widget.verticalPageIndex, widget.horizontalpageIndex);
          //   ApiAdapter.patchFeedback(widget.resultFeedback.id, viewed: true).then((value) {
          //     if(value == 200){
          //       print('ok ok ok ok ok');
          //       feedbackModel.setPoint();
          //     }
          //   });
          //   // .then((value) {
          //   // print('ok ok ok ok ok');
          //   // feedbackModel.setPoint();
          //   print('ok2 ok2 ok2 ok2 ok2');
          //   // Timer(Duration(milliseconds: 500), () {
          //   setState(() {
          //     //바텀네비 숫자제어
//     Provider.of<TabPageProvider>(context, listen: false).setCounterForFeedback(1);
          //     // feedbackModel.setShowPluse(false);
          //     // showPluse = false;
          //     print('ok3 ok3 ok3 ok3 ok3');
          //     feedbackModel.setPointRecord(feedbackModel.userPoint.value);
          //   });
          //   // });
          //   Timer(Duration(seconds: 2), () {
          //     feedbackModel.setShowPluse(false);
          //   });
          //   print('TabPageProvider TabPageProvider TabPageProvider ${Provider.of<TabPageProvider>(context, listen: false).counterForFeedback.value}');
          //   if(Provider.of<TabPageProvider>(context, listen: false).counterForFeedback.value == 0){
          //     _showDialog();
          //   }
          // }
if(feedbackModel.loop) {
            _controller.setLooping(true);
          }
if(!feedbackModel.loop) {
//마지막 비디오가아닐때
if(widget.verticalPageIndex < feedbackModel.playList.length - 1){
              feedbackModel.pageControllerMain.animateToPage(widget.verticalPageIndex + 1,
                duration: Duration(milliseconds: 300),
// curve: Curves.easeIn
curve: Curves.linear,
              );
            }else{
              _controller.setLooping(true);
            }
          }
        }
      };
      _controller.addListener(playListener);

    });
  }

voidinitThumbnails() {
// build()시마다 listener붙는 것을 방지하기 위해 미리 생성함.
for(vari = 0; i < feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length; i++) {
varthumbnailImage = NetworkImage('${feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex)[i].feedback.thumbnail}');
      thumbnailImage.resolve(ImageConfiguration())
          .addListener(ImageStreamListener(
              (info, call) {
// called after image loading.
varvIdx = widget.verticalPageIndex;
varhIdx = i;

//내 것을 true로 설정.
feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][0] =true;
            print("thumbnailLoadingIsDone[${vIdx}][${hIdx}] = true");
          }
      ));

      thumbnails.add(thumbnailImage);
    }
  }

  @override
voidinitState() {
super.initState();
    feedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);
    initController();
    getFavorate();
    getLike();
    setViewLike();

// initialize thumbnail networkimage
initThumbnails();

//포임트
// getPoint();

    // getViewed();
WidgetsBinding.instance.addPostFrameCallback((_) {});
  }

//포인트 반아오기
// getPoint() async {
  //   userId = SharedPrefs().userId;
  //   // int _selectedBookId = SharedPrefs().bookId;
  //   //현제 포인트
//   GetPoint getPoint = await ApiAdapter.getUserPoint(userId);
  //   if (mounted) {
  //     setState(() {
  //       _getPoint = getPoint;
  //       userPoint = getPoint.pointResults.first.amount;
  //     });
  //   }
  // }

setViewLike() {
if(widget.resultFeedback !=null) {
      setState(() {
        viewedInt = widget.resultFeedback.feedback.view;
        likedInt = widget.resultFeedback.feedback.like;
      });
    }
  }

  getFavorate()async{
if(widget.resultFeedback.saved) {
// setState(() {
feedbackModel.favorate =true;
// });
}else{
// setState(() {
feedbackModel.favorate =false;
// });
}
  }

  getLike()async{
if(widget.resultFeedback.liked) {
      setState(() {
        liked =true;
      });
    }else{
      setState(() {
        liked =false;
      });
    }
  }

  @override
voiddispose() {
//비디오 로딩 취소 마킹
varvIdx = widget.verticalPageIndex;
varhIdx = widget.horizontalpageIndex;

//내 것을 false로 설정.
    // feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][1] = false;
    // feedbackModel.thumbnailLoadingIsDone[vIdx][hIdx][0] = false;
    // print("thumbnailLoadingIsDone[${vIdx}][${hIdx}] = false");
    // print("thumbnailLoadingIsDone[${vIdx}][${hIdx}] = false");

    // _controller.dispose();
super.dispose();
    _controller.pause();
    _controller?.dispose();
  }

voidupdatePanelOpened() {
if(playerExpandProgress.value > 80 && !panelOpened.value && widget.verticalPageIndex == widget.currentVertical
        && widget.horizontalpageIndex == widget.currentHorizontal){
      _controller.pause();
      print('열림 열림 열림 열림 열림 열림 열림 열림 열림 열림 열림 ');
// setState(() {
panelOpened.value =true;
//페넬 열렸을때 비디오 멈추기
// _controller.pause();
      // });
      // _controller.pause();
}else if(playerExpandProgress.value < 80 && panelOpened.value && widget.verticalPageIndex == widget.currentVertical
        && widget.horizontalpageIndex == widget.currentHorizontal){
      print('닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 닫힘 ');
// setState(() {
panelOpened.value =false;
//페넬 닫혔을때 비디오 시작
_controller.play();
// });
}
  }

  @override
  Widget build(BuildContext context) {
//build바로 밑에 setState가 될만한게있음 에러
// Future.delayed(Duration.zero, () async {
updatePanelOpened();
// });
if(widget.verticalPageIndex == widget.currentVertical
        && widget.horizontalpageIndex == widget.currentHorizontal
        && !widget.verticalIsOnPageTurning
        && !widget.horizontalIsOnPageTurning
        && initialized
        && !panelOpened.value
//아래 조건 2개는 완전히 페이지가 정지했는지를 판별하기 위함.
&& (widget.currentVerticalPageDouble == widget.currentVerticalPageDouble.toInt())
        && (widget.currentHoriDouble == widget.currentHoriDouble.toInt())
    ) {

      _controller.play();
    }else{
if(widget.verticalPageIndex != widget.currentVertical
          || widget.horizontalpageIndex != widget.currentHorizontal
              && panelOpened.value
// && playerExpandProgress.value > 80
&& initialized) {
        _controller.pause();
        _controller.seekTo(Duration(milliseconds: 0));
        vapiController.adjust();
        vapiController.stop();
      }else{
        _controller.pause();
        vapiController.stop();
      }
    }

// });

returnScaffold(
      key: _scaffoldKey,
      body: !_controller.value.initialized
// && _getPoint == null
? Stack(
        children: [
          Container(
            color: Colors.black87,
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
          ),
          Positioned(
            top: 0,
            child: Container(
              padding: EdgeInsets.only(left: 10, right: 10, top: 40, bottom: 5),
              height: 16.0.h,
              width: MediaQuery.of(context).size.width,
              color: Colors.black.withOpacity(0.5),
// color: Colors.grey,
),
          ),
          Positioned(
// bottom: 8.0.h,
            // height: 12.7.h,
bottom: 0,
            height: 12.7.h,
            child: Container(
              padding: EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 20),
              width: MediaQuery.of(context).size.width,
              color: Colors.black.withOpacity(0.5),
// color: Colors.grey,
),
          ),
          Positioned(
// bottom: 20.0.h,
            // left: 0,
            // right: 0,
bottom: 12.0.h,
            left: 0,
            right: 0,
            child: LinearProgressIndicator(
              backgroundColor: Colors.black12,
              valueColor: AlwaysStoppedAnimation<Color>(Colors.white30),
            ),
          ),
        ],
      )
          : Stack(
        children: <Widget>[
          Container(
            color: Colors.black,
            child: Center(
              child: AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: Center(child: VideoPlayer(_controller)),
              ),
            ),
          ),
          _playControll(),
        ],
      ),
    );
  }

  Widget _playControll() {
finaldouble statusBarHeight = MediaQuery.of(context).padding.top;
finaldouble bottomBarHeight = MediaQuery.of(context).padding.bottom;

// print('hohohohohoho ${_controller.value.duration.inMilliseconds}');
    // print('hohohohohoho ${_controller.value.duration.inMicroseconds}');
    // print('hohohohohoho ${_controller.value.position.inMilliseconds}');
    // print('hohohohohoho ${_controller.value.position.inMicroseconds}');
    // print('hohohohohoho ${_controller.value.duration}');
    // print('_playControll() - statusBarHeight=${statusBarHeight},bottomBarHeight=${bottomBarHeight}');
returnContainer(
      color: Colors.transparent,
      child: !_controller.value.initialized
          ? Container(color: Colors.transparent)
          : Stack(
        children: [
///화면 탭 인지 부분
Positioned(
            top: statusBarHeight,
            child: GestureDetector(
              onTap: () {
// _controller.pause();
                // _showDialog();
print("tap");
                print("visibility : ${feedbackModel.visibility.toString()}");
// if (feedbackModel.panelController.isPanelOpen) feedbackModel.panelController.close();
if(mounted) {
                  setState(() {
                    feedbackModel.cancelTimer();
                    feedbackModel.setVisibility(!feedbackModel.visibility);
                    widget.setVerticalVisibility(feedbackModel.visibility);
// if (_controller.value.isPlaying) {
                    //   feedbackModel
                    //       .setTimer(Timer(Duration(seconds: 3), () {
                    //     if (_controller.value.isPlaying) {
                    //       if (mounted) {
                    //         setState(() {
                    //           feedbackModel.setVisibility(false);
                    //         });
                    //       }
                    //     }
                    //   }));
                    // }
});
                }
              },
              child: Container(
                color: Colors.transparent,
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height - statusBarHeight - 40.h,
// width: 100.0.w,
                // height: 40.0.h,
),
            ),
          ),

///exit버튼,단계버튼
Positioned(
            top: 0,
            child: AnimatedSwitcher(
              duration: Duration(milliseconds: 50),
              reverseDuration: Duration(milliseconds: 200),
              transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
              },
              child: Container(
                key: ValueKey(feedbackModel.visibility),
                child: feedbackModel.visibility
                    ? Container(
                  padding: EdgeInsets.only(left: 5.0.w, right: 5.0.w),
                  width: 100.0.w,
                  color: Colors.black.withOpacity(0.2),
                  child: Column(
                    children: [
                      SizedBox(height: 10.0.h,),
                      Container(
                          height: 10.0.h,
                          width: MediaQuery.of(context).size.width,
                          child: ListView.builder(
                            itemCount: feedbackModel.playListUnviewd.values.elementAt(widget.verticalPageIndex).length,
                            shrinkWrap:true,
                            scrollDirection: Axis.horizontal,
                            itemBuilder: (context, position) {
if(position == widget.horizontalpageIndex) {
returnPadding(
                                  padding:constEdgeInsets.only(left: 10.0),
                                  child: Column(
                                    children: [
                                      Container(
                                        child: FittedBox(
                                          fit: BoxFit.contain,
                                          child: CircleAvatar(
                                            radius: 30.sp,
                                            backgroundColor: feedbackModel
                                                .playListUnviewd.values.elementAt(widget.verticalPageIndex)[position]
                                                .viewed
                                                ? Colors.transparent
: Colors.redAccent,
                                            child: CircleAvatar(
                                              backgroundColor: Colors.transparent,
                                              backgroundImage: thumbnails[position],
                                              radius: feedbackModel
                                                  .playListUnviewd.values.elementAt(widget.verticalPageIndex)[position]
                                                  .viewed
                                                  ? 30.sp
                                                  : 28.sp,
                                              child: Stack(
                                                children: [
                                                  Visibility(
                                                      child: Container(
                                                        width: 10.0.w,
// height: 5.0.h,
child: Center(
                                                          child:
                                                          Lottie.asset("assets/play_button.json",
                                                              width: 100, repeat:true, fit: BoxFit.cover),
// Icon(
                                                          //   Icons.play_circle_fill,
                                                          //   color: Colors.red,
                                                          //   size: 10.0.w,
                                                          // ),
),
                                                      )),
                                                ],
                                              ),
                                            ),
                                          ),
                                        ),
                                      ),
                                      Expanded(
                                        child: Text(
                                          '${position + 1}단계',
                                          style: TextStyle(
                                            color: Colors.white,
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                );
                              }else{
returnInkWell(
                                    onTap: () {
                                      widget.onButtonTapped(position);
                                    },
                                    child: Padding(
                                      padding:constEdgeInsets.only(left: 10.0),
                                      child: Column(
                                        children: [
                                          Container(
                                            child: CircleAvatar(
                                              radius: 30.sp,
                                              backgroundColor: feedbackModel
                                                  .playListUnviewd.values.elementAt(widget.verticalPageIndex)[position]
                                                  .viewed
                                                  ? Colors.transparent
: Colors.redAccent,
                                              child: CircleAvatar(
                                                backgroundColor: Colors.transparent,
                                                backgroundImage: thumbnails[position],
                                                radius: feedbackModel
                                                    .playListUnviewd.values.elementAt(widget.verticalPageIndex)
                                                [position]
                                                    .viewed
                                                    ? 30.sp
                                                    : 28.sp,
                                              ),
                                            ),
                                          ),
                                          Expanded(
                                            child: Text(
                                              '${position + 1}단계',
                                              style: TextStyle(
                                                color: Colors.white,
                                              ),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ));
                              }
                            },
                          )),
                    ],
                  ),
                )
                    : Container(),
              ),
            ),
          ),

///play, prev, next버튼 영역
Positioned(
            child: Center(
              child: AnimatedSwitcher(
                duration: Duration(milliseconds: 50),
                reverseDuration: Duration(milliseconds: 200),
                transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
                },
                child: Container(
                  key: ValueKey(feedbackModel.visibility),
                  width: double.infinity,
                  child: feedbackModel.visibility
                      ?
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Material(
                        color: Colors.transparent,
                        child: InkWell(
                          customBorder: CircleBorder(),
                          onTap: ()async{
await_controller.seekTo(await_controller.position - Duration(seconds: 3));
// indicator재조정
vapiController.adjust();
                          },
                          child: Padding(
                            padding:constEdgeInsets.all(15),
                            child: Image.asset(
                              'assets/rewind.png',
                              width: 15.0.w,
                              color: Colors.black.withOpacity(0.2),
                            ),
                          ),
                        ),
                      ),
                      Container(width: 10,),
                      Material(
                        color: Colors.transparent,
                        child: InkWell(
                            customBorder: CircleBorder(),
                            onTap: () {
if(mounted) {
if(_controller.value.isPlaying) {
                                  _controller.pause();
                                  setState(() {
                                    initialized =false;
                                  });
                                  feedbackModel.cancelTimer();
                                  feedbackModel.setVisibility(true);
// stop indicator
vapiController.stop();
                                }else{
if(_controller.value.position == _controller.value.duration) {
                                    _controller.initialize();
                                    setState(() {
                                      initialized =true;
                                    });
                                    _controller.play();
                                  }else{
                                    setState(() {
                                      initialized =true;
                                    });
                                    _controller.play();
                                  }
                                  feedbackModel.setTimer(Timer(Duration(seconds: 3), () {
if(_controller.value.isPlaying)if(mounted) {
                                      setState(() {
                                        feedbackModel.setVisibility(false);
                                      });
                                    }
                                  }));

// start indicator
vapiController.play();
                                }
                              }
                            },
                            child: Padding(
                              padding:constEdgeInsets.all(15),
                              child: Icon(
                                _controller.value.isPlaying ? Icons.pause: Icons.play_arrow,
                                color: Colors.black.withOpacity(0.2),
                                size: 15.0.w,
                              ),
                            )),
                      ),
                      Container(width: 10,),
                      Material(
                        color: Colors.transparent,
                        child: InkWell(
                          customBorder: CircleBorder(),
                          onTap: ()async{
if(_controller.value.duration - _controller.value.position <
                                Duration(seconds: 6)) {
await_controller.seekTo(Duration.zero);
                            }else{
await_controller.seekTo(await_controller.position + Duration(seconds: 3));
                            }
// indicator재조정
vapiController.adjust();
                          },
                          child: Padding(
                            padding:constEdgeInsets.all(15),
                            child: Image.asset(
                              'assets/forward.png',
                              width: 15.0.w,
                              color: Colors.black.withOpacity(0.2),
                            ),
                          ),
                        ),
                      ),
                    ],
                  )
                      : Container(),
                ),
              ),
            ),
          ),

//viewd랑 좋아요
Positioned(
              bottom: 22.0.h,
              right: 2.0.w,
// bottom: 20.0.h,
child: AnimatedSwitcher(
                duration: Duration(milliseconds: 50),
                reverseDuration: Duration(milliseconds: 200),
                transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
                },
                child: Container(
                  key: ValueKey(feedbackModel.visibility),
                  child: feedbackModel.visibility
                      ? Container(
                    width: 100.0.w,
                    height: 25.0.h,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.end,
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: [
                        Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            IconButton(
                                icon: Icon(
                                  Icons.visibility, color: Colors.white,
                                ),
                                iconSize: 8.0.w
// fit: BoxFit.cover,
),
                            Container(
                              width: 8.0.w,
                              child: Center(
                                child: Text(
                                  '$viewedInt',
                                  style: TextStyle(color: Colors.white, fontSize: 12.0.sp),
                                ),
                              ),
                            ),
                            SizedBox(
                              height: 1.0.h,
                            ),
                            InkWell(
                                onTap: () {
// feedbackModel.setliked(widget.resultFeedback.id, liked, widget.verticalPageIndex, widget.horizontalpageIndex);
if(liked) {
                                    feedbackModel.setliked(widget.resultFeedback.id,false,
                                        widget.verticalPageIndex, widget.horizontalpageIndex);
                                    setState(() {
                                      liked = !liked;
                                      likedInt -= 1;
                                    });
                                    _scaffoldKey.currentState
                                        .showSnackBar(CustomMessage.displaySnackBar('좋아요 영상에서 해제되었습니다'));
                                  }else{
                                    feedbackModel.setliked(widget.resultFeedback.id,true,
                                        widget.verticalPageIndex, widget.horizontalpageIndex);
                                    setState(() {
                                      liked = !liked;
                                      likedInt += 1;
                                    });
                                    _scaffoldKey.currentState
                                        .showSnackBar(CustomMessage.displaySnackBar('영상이 좋아요에 등록이 되었습니다'));
                                  }
                                },
                                child:
                                IconButton(
                                    icon:
                                    !liked ? Icon(Icons.favorite_border_outlined,
                                      color: Colors.white,) : Icon(
                                      Icons.favorite_outlined, color: Colors.white,
                                    ),
                                    iconSize: 8.0.w
// fit: BoxFit.cover,
)
                            ),
                            Container(
                              width: 8.0.w,
                              child: Center(
                                child: Text(
                                  '$likedInt',
                                  style: TextStyle(color: Colors.white, fontSize: 12.0.sp),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  )
                      : Container(),
                ),
              )),

//로딩
if(_controller.value.initialized &&
              _controller.value.duration.inMilliseconds > 0)
            Positioned(
                bottom: 20.0.h,
// bottom: 12.0.h,
child: AnimatedContainer(
                    duration: Duration(milliseconds: 50),
                    child: Opacity(
                      opacity: feedbackModel.visibility && !feedbackModel.pageMoving.value ? 1 : 0,
                      child: Container(
                        child: Padding(
                          padding:constEdgeInsets.symmetric(vertical: 4),
                          child: Container(
                            height: 1,
// height: 37,
width: MediaQuery.of(context).size.width,
                            child: VideoAppProgressIndicator(
                                vapiController: vapiController,
                                controller: _controller,
                                dur: _controller.value.duration.inMilliseconds
                            ),
                          ),
                        ),
                      ),
                    )
                )),

//시간표시
if(!feedbackModel.pageMoving.value)
            Positioned(
                bottom: 21.0.h,
                right: 0,
// bottom: 13.0.h,
                // right: 0,
child: AnimatedSwitcher(
                  duration: Duration(milliseconds: 50),
                  reverseDuration: Duration(milliseconds: 200),
                  transitionBuilder: (Widget child, Animation<double> animation) {
returnFadeTransition(opacity: animation, child: child);
                  },
                  child: Container(
                    key: ValueKey(feedbackModel.visibility),
                    child: feedbackModel.visibility
                        ? ValueListenableBuilder(
                      valueListenable: _controller,
                      builder: (context, VideoPlayerValue value, child) {
                        Duration millis = value.duration - value.position;
varseconds = millis.inSeconds;
finaldays = seconds ~/ Duration.secondsPerDay;
                        seconds -= days * Duration.secondsPerDay;
finalhours = seconds ~/ Duration.secondsPerHour;
                        seconds -= hours * Duration.secondsPerHour;
finalminutes = seconds ~/ Duration.secondsPerMinute;
                        seconds -= minutes * Duration.secondsPerMinute;

finalList<String> tokens = [];
if(days != 0) {
                          tokens.add('${days}d');
                        }
if(tokens.isNotEmpty || hours != 0) {
                          tokens.add('${hours}h');
                        }
if(tokens.isNotEmpty || minutes != 0) {
                          tokens.add('${minutes}m');
                        }
                        tokens.add('${seconds}s');
//타이머 투명처리
returnText(
                          tokens.join(':').toString(),
                          style: TextStyle(color: Colors.transparent, fontSize: 12),
                        );
                      },
                    )
                        : Container(),
                  ),
                )),
        ],
      ),
    );
  }

  Future<bool> onLikeButtonTapped(bool isLiked)async{
if(liked) {
      feedbackModel.setliked(widget.resultFeedback.id,false,
          widget.verticalPageIndex, widget.horizontalpageIndex);
      setState(() {
        liked = !liked;
        likedInt -= 1;
      });
      _scaffoldKey.currentState
          .showSnackBar(CustomMessage.displaySnackBar('좋아요 영상에서 해제되었습니다'));
    }else{
      feedbackModel.setliked(widget.resultFeedback.id,true,
          widget.verticalPageIndex, widget.horizontalpageIndex);
      setState(() {
        liked = !liked;
        likedInt += 1;
      });
      _scaffoldKey.currentState
          .showSnackBar(CustomMessage.displaySnackBar('영상이 좋아요에 등록이 되었습니다'));
    }
return!isLiked;
  }

void_showDialog() {
finalfeedbackModel = Provider.of<FeedbackTabProvider>(context, listen:false);
    showDialog(
      context: context,
      barrierDismissible:false,
      builder: (BuildContext context) {
returnAlertDialog(
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
          content: SingleChildScrollView(
            child: Column(
              children: [
                Padding(
                  padding:constEdgeInsets.symmetric(vertical: 10.0),
                  child: Container(height: 6.0.h, child: Image.asset("assets/coin.png")),
                ),
                Container(
                  height: 10.h,
                ),
                Text(
                  "총 ${feedbackModel.unviewCount * 5}포인트 획득",
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 13.0.sp,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                Text(
                  "영상을 모두 시청하였어요!",
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 13.0.sp,
                  ),
                ),
              ],
            ),
          ),
          actions: <Widget>[
            SizedBox(
              width: MediaQuery.of(context).size.width,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  ElevatedButton(
                    style: ElevatedButton.styleFrom(
                      primary: Colors.grey[300],
                      onPrimary: Colors.black,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(32.0),
                      ),
                    ),
                    child: Container(
                      width: 20.0.w,
                      child: Center(
                        child: Text(
                          "계속 보기",
                          style: TextStyle(
                            fontSize: 15.sp,
                            color: Colors.black,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                    ),
                    onPressed: () {
                      Navigator.pop(context);
                      setState(() {
                        initialized =true;
                      });
                    },
                  ),
                  ElevatedButton(
                    style: ElevatedButton.styleFrom(
                      primary: Colors.black,
                      onPrimary: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(32.0),
                      ),
                    ),
                    child: Container(
                      width: 20.0.w,
                      child: Center(
                        child: Text(
                          "홈으로",
                          style: TextStyle(
                            fontSize: 15.sp,
                            color: Colors.white,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                    ),
                    onPressed: () {
if(_controller.value.isPlaying) _controller.pause();
if(initialized =true) {
                        setState(() {
                          initialized =false;
                        });
                      }
                      Navigator.pushReplacement<void,void>(
                        context,
                        MaterialPageRoute<void>(
                          builder: (BuildContext context) => TabPage(),
                        ),
                      );

// setState(() {
                      //   _controller = null;
                      // });
},
                  ),
                ],
              ),
            ),

          ],
        );
      },
    );
  }

}