0% found this document useful (0 votes)
212 views102 pages

Flutter Live Streaming App Report

This document is a project report on developing a live streaming application called Playsar using Flutter. It was submitted by three students - Mohd Hashim, Madhavi Singh, and Mohd Farman - to fulfill the requirements for a Bachelor of Technology degree in Computer Science Engineering. The report includes an introduction to the project, analysis of system requirements, details of the technologies used including Flutter and Node.js, coding details, directory structure, testing procedures, and screenshots of the application.

Uploaded by

Mohd Hashim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
212 views102 pages

Flutter Live Streaming App Report

This document is a project report on developing a live streaming application called Playsar using Flutter. It was submitted by three students - Mohd Hashim, Madhavi Singh, and Mohd Farman - to fulfill the requirements for a Bachelor of Technology degree in Computer Science Engineering. The report includes an introduction to the project, analysis of system requirements, details of the technologies used including Flutter and Node.js, coding details, directory structure, testing procedures, and screenshots of the application.

Uploaded by

Mohd Hashim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 102

A Project Report

On
LIVE STREAMING APPLICATION USING FLUTTER
(PLAYSAR)

Submitted in partial fulfillment of the requirement for the award of the degree of
BACHELOR OF TECHNOLOGY
IN
COMPUTER SCIENCE ENGINEERING
By:
MOHD HASHIM (100190133)

MOHD FARMAN (100190132)

MADHAVI SINGH (100190129)

UNDER THE GUIDANCE OF

Er. MILIND (Asst. Professor & Co-ordinator, CSE)

DEPARTMENT OF COMPUTER SCIENCE ENGINEERING

SIR CHHOTU RAM INSTITUTE OF ENGINEEERING &TECHNOLOGY

CHAUDHARY CHARAN SINGH UNIVERSITY, MEERUT

i
Sir Chhotu Ram Institute Of Engg. & Tech.
Approved by A.I.C.T.E., New Delhi

Chaudhary Charan Singh University Meerut Campus

CERTIFICATE-I

This is to certify that this project report entitled “LIVE STREAMING APPLICATION
USING FLUTTER” which is submitted by Mohd Hashim(100190133), Madhavi
Singh(100190129), Mohd Farman(100190132), in the partial fulfillment of the requirement for
the award of degree of Bachelor of Technology in Computer Science Engineering from this
college is a record of candidate own work carried out by him/her under our supervision.
The matter embodied in this Project Report has not been submitted earlier for award of any degree
or diploma in any university/institution to the best of our knowledge & belief.

(……..…………..) (..………………….)
(Project Guide) (Project Co-ordinator)

Date: //

ii
Sir Chhotu Ram Institute Of Engg. & Tech.
Approved by A.I.C.T.E., New Delhi

Chaudhary Charan Singh University Meerut Campus

CERTIFICATE-II

The project report entitled “LIVE STREAMING APPLICATION USING FLUTTER


(PLAYSAR)” which is submitted by Mohd Hashim(100190133), Madhavi Singh(100190129),
Mohd Farman(100190132), it warrants its Acceptance as a prerequisite for the Bachelor of
Technology in Computer Science Engineering from this college is a record of candidate own
work carried out by him/her under our supervision.

(……………….) (………..……….)
Internal Examiner External Examiner

(………………….)
(Co-ordinator)
Department of (CSE)

(…….………………)
Director, SCRIET

iii
ACKNOWLEDGEMENT

It gives me a great sense of pleasure to present the report of the Project Work undertaken
during B. Tech. Final Year. I owe special debt of gratitude to my Project Coordinator Er. Ritu
Sharma, Department of Computer Science Engineering, SCRIET C.C.S. University, Meerut for
her/his constant support and guidance throughout the course of my work. It is only her/his
cognizant efforts that my endeavors have seen light of the day.

My deepest thanks to my Project Guide Er. Milind Co-ordinator ,CSE, SCRIET, CCS University
Meerut, forguiding throughout the project.

I also take the opportunity to acknowledge the contribution of Prof. Neeraj Singhal, Director,
SCRIET CCS University, Meerut and Er.Milind, Assistant Professor & Coordinator
Department of Computer Science Engineering, SCRIET, Meerut for his full support and
assistance during the development of the project.

I also do not like to miss the opportunity to acknowledge the contribution of all faculty members
of the department for their kind assistance and cooperation during the development ofmy project.

Last but not the least, I acknowledge my friends for their contribution in the completion of the
project.

Mohd Hashim (100190133)

Mohd Farman (100190132)

Madhavi Singh (100190129)

iv
INDEX

Front page i
Declaration ii
Certification iii
Acknowledgement iv
Table of contents 1
Abstract 3

CHAPTER
1. INTRODUCTION……………………………………………. 4-5
1.1 Objectives 4
1.2 Overview 4
1.3 Proposed System 5
2. SYSTEM ANALYSIS…………………………………………...6-9
2.1 Objective 6
2.2 SDLC Phases 6-7
2.3 Class Diagram 8
2.4 Architecture of Playsar 9
3. TECHNOLOGY…………………………………………..10-11
3.1 Introduction of Flutter 10
3.1.1 Features
3.2 Node Js server 11
3.2.1 feature 0f js
3.3 Software requirement Specification 12
3.3.1 Functional Requirement
3.3.2 Hardware Requirement
3.3.3 Software Requirement

4. CODING…………………………………………………13-82
4.1 Backend Coding 13
4.1.1 package Jason
4.1.2 Routers
4.2 Backend Coding 29
4.2.1 Widgets
4.3 Data 60
4.4 Domain 73

1
4.5 Bloc 75
5. DIRECTORY STRUCTURE………………………………83-85
5.1 D structure 83
5.2 Front End directory Structure 84
5.3 Back End Directory Structure 85
6. TESTING AND SCREENSHOTS ……………………….86-96
6.1 Testing 86
6.2 Types of Testing 86
6.3 Screenshots 87
7. CONCLUSION ………………………………………………..97
8. REFERENCE………………………………………………….98

2
ABSTRACT

We are developing a “Playsar” by taking advantages of the flutter platform. The main concept of
this project is to build a Mobile Application, which should be able to allow people to give entertain
-ment and show all some live Indian news channel.
Time saving working load reduce. This app including the features of trending entertainment
movies, web- series, live news channels and comedies .
This is a simple, safe and secure method that takes minimum of time. We are to maintaining a
server by using node JS also express JS for routing.

Live streaming services whereby video is broadcast in real time, have been adopted by many
small individual sellers as a direct selling tool. Drawing on literature in retailing, adoption behavior,
and electronic commerce, this paper proposes a comprehensive framework with which to examine
the relationships among customers' perceived value of live streaming, customer trust, and
engagement. Symbolic value is found to have a direct and indirect effect via trust in sellers on
customer engagement, while utilitarian and hedonic values are shown to affect customer
engagement indirectly through customer trust in products and trust in sellers sequentially.
Elucidating the role of live streaming in increasing sales and loyalty, these findings suggest different
routes through which small online sellers can build customer engagement with two types of trust
as mediators. Theoretical and managerial implications of this analysis for social commerce are
further discussed at the conclusion of this paper.

3
CHAPTER 1
INTRODUCTION
“PLAYSAR” is an Live Video Streaming app. In which user can view the trending movies,
web-series and live tele channel. There is a NodeJS using for back-end server management and
Flutter using for front-end app development.

1.1 Objective
 To develop live video streaming app.
 To implement live news broadcast ...
 To develop custom video streaming app.
 To establish the connection b/w user and server provider.
 To provide the better quality of video streaming.
 To provide video streaming in better quality, audio filter, video orientation, subtitle and
playback speed management

1.2 Overview

Video streaming has received much attention for some time now, and its popularity has grown
manifold in the last decade, particularly with the deployment of widely known video streaming
services, such as YouTube, Netflix, Hulu, Daily Motion, and others. Video streaming now accounts
for a large share of the total traffic the Internet, and as such the transmission mechanisms used by
video servers have an impact not only on the quality of the video presentation to the clients, but also
on the total traffic impact on the network. Video streaming, in various forms of video on demand
(VOD), live, and 360 degree streaming, has grown dramatically during the past few years. In
comparison to traditional cable broadcasters whose contents can only be watched on TVs, video
streaming is ubiquitous and viewers can flexibly watch the video contents on various devices,
ranging from smartphones to laptops, and large TV screens. Such ubiquity and flexibility are enabled
by interweaving multiple technologies, such as video compression, cloud computing, content
delivery networks, and several other technologies. As video streaming gains more popularity and
dominates the Internet traffic, it is essential to understand the way it operates and the interplay of
different technologies involved in it. Accordingly, the first goal of this paper is to unveil
sophisticated processes to deliver a raw captured video to viewers’ devices. In particular, we
elaborate on the video encoding, transcoding, packaging, encryption, and delivery processes. We
survey recent efforts in academia and industry to enhance these processes. As video streaming
industry is increasingly becoming reliant on cloud computing, the second goal of this survey is to
explore and survey the ways cloud services are utilized to enable video streaming services. The third
goal of the study is to position the undertaken research works in cloud-based video streaming and
identify challenges that need to be obviated in future to advance cloud-based video streaming
industry to a more flexible and user-centric service.

4
1.3 Project modules of Live Streaming Application:

 Accounts:In this module user can register by entering their profile information. After
registration user can access accounts page by entering login id and password.

 Video manager: This module allows user to upload videos and they can edit uploaded
videodescription and its contents.

 My Channel:In this module the visitors can add or subscribe users channel by entering
theirEmail ID. Whenever the user uploads new video it sends mail notification to the visitor.

 Events broadcasting: This module can be used to broadcast a live events. The Live module
home page contains list of events and Completed Events sections.The user needs to enter event
name, event date, event time, etc.

 Dashboard module: There are two types of users in this module. They are administrator
andemployees.

 Live broadcasting: This module is for administrator where administrator can stream
TVchannels by entering embedded link.

 Subscription: In this module user can subscribe for live broadcasting by making payment.
Afterconfirmation of the payment the user can watch and record videos. The subscribed member
can download the videos by clicking download button.

 Comments and likes:The registered user can post their comments and like the uploaded videos.

5
CHAPTER 2
SYSTEM ANALYSIS

2.1 Objective
The specific objectives of the project include:
 To develop live video streaming app.
 To implement live news broadcast ...
 To develop custom video streaming app.
 To establish the connection b/w user and server provider.
 To provide the better quality of video streaming.
 To provide video streaming in better quality, audio filter, video orientation, subtitle and
play back speed management .

2.2 SDLC Phases


System Development Life Cycle (SDLC) mainly consists of the following 7 phases which can
be detailed:-
1. Feasibility Study
This is the measure of how beneficial or practical the development of an information system will
be to an organization. It is aimed at establishing whether it is worthwhile developing the new system.
This are introduces the system in terms of research into why it is more viable than the existing system.
Three main areas of feasibility study are identified. Operational Feasibility, Technical Feasibility,
Economical Feasibility Schedule Feasibility. The Following study was carried out to establish
whether the system development will carry on to the next stage.
2. Request Approval
Request approval is the third phase of system development lifecycle. Request approval is the
phase in which all the requirement which would be provide in the system are stated. The request
approval is a sort of agreement between the client and the company which is building this software.
Both the parties should be mutually agreed on the stated requirement.
3. System Analysis
System analysis is the phase following the phase of the request approval. In this phase we tend
to analysis the overall system which we have to build. System analysis is the crucial part in SDLC.

6
4. System Design
System design means the design of the system. The system can be done in either of the
following two ways:-
 Logical System Design
 Physical System Design

5. Coding
Coding is the phase in which a developer codes using any programming language. Coding
constitution only 20% of the whole project and which is easier to write. The coding work is also
done in the terms; development of the system is usually done under the modular programming style,
which can be either top-down approach or bottom-up approach.
6. Testing
Testing is the phase in which the system that has been developed is tested. Testing comprises
of the 60% of the overall development of the system. Testing of the system is important because
testing aims to uncover the different errors in the system. There are various different testing
techniques that can be used for the testing of the system.
7. Implementation
Implementation process involved the installation of software on user’s side. Implementation
process actually depends on types of a system & various. Opting for suitable conversion approach
is step implementation. The conversion process are as follows.
 Bloc Pattern

8. Maintenance
Merely developing the system is not import but also maintenance is important. The company
that has built the system provides for some time free of cost maintenance to the client and after that
period it is usually a paid service.

7
2.3 Class Diagram

8
2.4 Architecture of playsar

PlaySAR

Play
series
Play
movie

Play
channel

Play music

9
CHAPTER 3
TECHNOLOGY USED

3.1 Introduction of Flutter

3.1.1 What is Flutter?

• Flutter isGoogle's free and open-


source UI framework for creating native mobile applications Released in  Flutter allows
devel opers to build mobile applications with a single codebase and programming language This
capabil ity makes building both iOS and Android apps simpler and faster

3.1.2 Features of Flutter:

• Open-source Platform. Flutter is an open-source platform developed and backed by Google. ...
• Hot Reload. ...
• Rich Widgets. ...
• Single Code Base. ...
• Google Firebase Support. ...
• Rapid App Development. ...
• Single Codebase for Both Platforms. ...
• Expressive Interfaces.

Version of Flutter

Date /Name Version Remarks

Flutter SDK 2.5.0 Version information: 2.5.0

FVM 1.0 FVM 2.5.0,2.10.5 etc

January 2 0 1 7 1.0.0 Initial Released

10
3.2 NodeJS SERVER

Node. js is a server-side JavaScript run-time environment. It's open-source, including


Google's V8 engine, Libuv for cross-platform compatibility, and a core library.

3.2.1 Features of NodeJS

• Asynchronous and Event Driven − All APIs of Node. js library are asynchronous, that is,
non-blocking. ...
• Very Fast − Being built on Google Chrome's V8 JavaScript Engine, Node. js library is
very fast in code execution.
• Single Threaded but Highly Scalable − Node. ...
• No Buffering − Node. ...
• License − Node.

3.3 Software Requirement Specification


3.3.1 Functional Requirement
Functional requirement are those requirement which affect the system. These requirements makes
the system working. Following points describe the requirements of the users for the new proposed
system:

 System should be connected with internet.


 System should be charged .

3.3.2 Hardware Requirements


Processor: Intel Core I5
Installed Memory (RAM):8.00 GB (256 GB USABLE)Hard Disk:

3.3.3 Software Requirements


Operating system :windows /Mac Programming language: Dart,JS
Backend-technology: Nodejs , Mongo DB Front-End: Flutter

11
CHAPTER 4
CODING

4.1 Backend Coding


1. Server.js

const express = require('express');


const cors = require('cors');

const app = express();

const token =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJIcml0aWsiLCJuYW1lIjoiWW91d2lsbG5ldmVyZ2V0aXQiLCJpY
XQiOjE1MTYyMzkwMjJ9.6PRPWzmu_or76BASRLuP59ALvgWdQ8viGM9aThRojyY';

app.use(express.json());
app.use(cors());

//India channel list router


const indianChannelList = require('./routers/indian_channel_list');
app.use('/indianChannelList',authorization ,indianChannelList);

//animeList
const animeList = require('./routers/anime_list');
app.use('/animeList',authorization ,animeList);

//home page
//Trending List
const trendingList = require('./routers/trending');
app.use('/trendingList',authorization ,trendingList);

//Trending List
const newArrivalsList = require('./routers/new_arrivals');
app.use('/newarrivals',authorization ,newArrivalsList);

//featuredbanner
const featuredBanner = require('./routers/featuredBanner');
app.use('/featuredBanner',authorization ,featuredBanner);

//comming_soon
const comming_soon = require('./routers/comming_soon');
app.use('/commingsoon',authorization,comming_soon);

//movie categories

//animationMovieCategory
const AnimatedMovies = require('./routers/Animated_movies');
app.use('/animatedMovies',authorization,AnimatedMovies);

//horror movies category


const horrorMovies = require('./routers/horror_movies');
app.use('/horrorMovies',authorization,horrorMovies);
12
//action movies category
const actionMovies = require('./routers/action_movie');
app.use('/actionMovies',authorization,actionMovies);

//series

//animated series
const animatedSeries = require('./routers/animated_series');
app.use('/animatedSeries',authorization,animatedSeries);

//horror series
const horrorSeries = require('./routers/horror_series');
app.use('/horrorSeries',authorization,horrorSeries);

//action series
const actionSeries = require('./routers/action_series');
app.use('/actionSeries',authorization,actionSeries);

//starting route
app.get('/', authorization ,(req,res) => {
if(req.Auth){
res.send("Server Connected");
}else{
res.send('Auth fail');
}

});

//authorization
function authorization(req,res,next){

const authHeader = req.headers['authorization'];


const reqtoken = authHeader && authHeader.split(' ')[1]; if
(reqtoken == null){

req.Auth = false;
}
if(reqtoken === token){

req.Auth = true;

}else{
req.Auth = false;

}
next();
}

const startServer = async () => {try {


const PORT = process.env.PORT || 3000;
app.listen(PORT, "192.168.1.9" ,() => {

13
console.log(`Server started on `+"192.168.1.9"+":"+PORT);
});
} catch (error) {
console.log(error);
}
}
startServer();

4.1.1 package.json
{
"name": "playsar",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon server.js"
},
"author": "Subhash Chandra Shukla",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}

4.1.2 Routers

1. ActionMovie.js

const express = require('express');


const router = express.Router();

const resJson_actionMoviesList = [
{
"name":"Godzilla vs Kong(Hindi audio)",
"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"Hindi",
"description":"Godzilla vs. Kong is a 2021 American monster film directed by Adam Wingard. A
sequel to Godzilla: King of the Monsters (2019) and Kong: Skull Island (2017), it is the fourth film
in Legendary's MonsterVerse. It is also the 36th film in the Godzilla franchise, the 12th film in the
King Kong franchise, and the fourth Godzilla film to be completely produced by a Hollywood studio.
The film stars Alexander Skarsgård, Millie Bobby Brown, Rebecca Hall, Brian Tyree Henry, Shun
Oguri, Eiza González, Julian Dennison, Lance Reddick, Kyle Chandler, and Demián Bichir. In the
film, Kong clashes with Godzilla as humans lure the ape into the Hollow Earth to retrieve a power
source for a weapon to stop Godzilla's mysterious rampages."
14
},
];

router.get('/', async (req,res) => {


if(req.Auth){
try {
res.status('200').send(resJson_actionMoviesList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

2. ActionSeries.js

const express = require('express');


const router = express.Router();

const resJson_actionSeriesList = [
{
"name":"ekk",
"logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"description":"this is new series",
"seasons":[
{
"seasonName" : "season1",
"seasonDescription":"this is first season",
"seasonLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg", "episodes":[
{
"episodeName":"episode1",
"episodeDescription":"this is first episode" ,

"episodeUrl":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"episodeLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg"
}
]

}
],
"language":"English"
},

];

15
router.get('/', async (req,res) => {
if(req.Auth){
try { res.status('200').send(resJson_actionSeriesList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

3. Animated Movies
const express = require('express');
const router = express.Router();

const resJson_animationMovieList = [
{
"name":"Panda Vs Aliens(720p)",
"logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"A group of aliens seek out to conquer new worlds and take particular notice of Earth, after seeing
satellite broadcasts of TV shows of a powerful panda, Pandy."
},

];

router.get('/', async (req,res) => {


if(req.Auth){
try { res.status('200').send(resJson_animationMovieList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

16
4. Animated Series

const express = require('express');


const router = express.Router();

const resJson_animatedSeriesList = [
{
"name":"ekk", "logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"description":"this is new series",
"seasons":[
{
"seasonName" : "season1",
"seasonDescription":"this is first season",
"seasonLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"episodes":[
{
"episodeName":"episode1", "episodeDescription":"this
is first episode" ,

"episodeUrl":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseli
ne.m3u8",
"episodeLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg"
}
]

}
],
"language":"English"
},

];

router.get('/', async (req,res) => {


if(req.Auth){
try {
res.status('200').send(resJson_animatedSeriesList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}});

module.exports = router;

17
5. AnimList.js

const express = require('express');


const router = express.Router();

const resJson_animeList = [
{
"name":"Rent a girlfriend",
"logo":"https://upload.wikimedia.org/wikipedia/pt/d/de/Kanojo%2C_Okarishimasu_poster.jpg",
"type":"m38u",
"url":"https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899- f0f6155f6efa.m3u8"
},

];

router.get('/', async (req,res) => {


if(req.Auth){
try { res.status('200').send(resJson_animeList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

6. ComingSoon.js

const express = require('express');


const router = express.Router();

const resJson_CommingSoon = [
{

"name":"Godzilla vs Kong(Hindi audio)",


"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg",
"type":"m38u",
"releaseDate":"21/06/2021",

},{

"name":"Godzilla vs Kong(Hindi audio)",


"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg",
"type":"m38u",
"releaseDate":"21/06/2021",

18
},{

"name":"Godzilla vs Kong(Hindi audio)",


"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg",
"type":"m38u",
"releaseDate":"21/06/2021",

},{

"name":"Godzilla vs Kong(Hindi audio)",


"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg",
"type":"m38u",
"releaseDate":"21/06/2021",

},
];

router.get('/', async (req,res) => {


if(req.Auth){
try {
res.status('200').send(resJson_CommingSoon);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

7. FeaturedBanner.js

const express = require('express');


const router = express.Router();

const resJson_featuredBanner = {

"name":"Godzilla vs Kong(Hindi audio)",


"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",

};

router.get('/', async (req,res) => {


if(req.Auth){
try {
19
res.status('200').send(resJson_featuredBanner);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});
module.exports = router;

8. horror_movie.js

const express = require('express');


const router = express.Router();

const resJson_horrorMoviesList = [

{
"name":"Blue call(360p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
xODA2MTA@._V1_FMjpg_UY682_.jpg",
"type":"m38u", "url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},
{
"name":"Blue call(720p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
xODA2MTA@._V1_FMjpg_UY682_.jpg",
"type":"m38u", "url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},
];

router.get('/', async (req,res) => {


20
if(req.Auth){
try { res.status('200').send(resJson_horrorMoviesList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});
module.exports = router;

9. horror_series.js
const express = require('express');
const router = express.Router();

const resJson_horrorSeriesList = [
{
"name":"ekk",
"logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"description":"this is new series",
"seasons":[
{
"seasonName" : "season1",
"seasonDescription":"this is first season",
"seasonLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg", "episodes":[
{
"episodeName":"episode1",
"episodeDescription":"this is first episode" ,

"episodeUrl":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"episodeLogo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg"
}
]

}
],
"language":"English"
},

];

router.get('/', async (req,res) => {


if(req.Auth){
try { res.status('200').send(resJson_horrorSeriesList);

21
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

10. indian_channel_list.js
const express = require('express');
const router = express.Router();

const resJson_IndianChannelList = [
{
"name": "&Flix",
"logo": "https://static.epg.best/in/AndFlix.in.png", "type":"m38u",
"url": "https://y5w8j4a9.ssl.hwcdn.net/andflixhd/tracks-v1a1/index.m3u8",
"category": "Movies"
},
{
"name": "&privé HD",
"logo": "https://upload.wikimedia.org/wikipedia/en/4/4f/Logo_of_%26_Priv%C3%A9_HD.jpg",
"type":"m38u",
"url": "https://y5w8j4a9.ssl.hwcdn.net/andprivehd/tracks-v1a1/index.m3u8",
"category": "Movies"
},
{
"name": "3 Tamil TV",
"logo": "https://i.imgur.com/WfAU7pB.png",
"type":"m38u",
"url": "https://6n3yogbnd9ok-hls-
live.5centscdn.com/threetamil/d0dbe915091d400bd8ee7f27f0791303.sdp/index.m3u8",
"category": "Entertainment"
},

{
"name": "7X Music",
"logo": "https://i.imgur.com/fD7wLka.jpg", "type":"m38u",
"url": "http://newsjatt.camdvr.org:1935/newsjatt/myStream/playlist.m3u8", "category":
"Music"
},
{
"name": "9XM",
"logo": "https://i.imgur.com/fD7wLka.jpg", "type":"m38u",
"url": "https://d2q8p4pe5spbak.cloudfront.net/bpk-tv/9XM/9XM.isml/index.m3u8",
"category": "Music"
},

22
{
"name": "Aaj Tak",
"logo": "https://upload.wikimedia.org/wikipedia/commons/a/ab/AT-New-Logo-800x600.png",
"type":"m38u",
"url": "https://feeds.intoday.in/aajtak/api/aajtakhd/master.m3u8", "category":
"News"
},
{
"name": "Aaj Tak (560p)",
"logo": "https://upload.wikimedia.org/wikipedia/commons/a/ab/AT-New-Logo-800x600.png",
"type":"m38u",
"url": "https://lmil.live-s.cdn.bitgravity.com/cdn-live/_definst_/lmil/live/aajtak_app.smil/playlist.m3u8", "category":
"News"
},
{
"name": "Aathavan TV",
"logo": "https://i.imgur.com/IgwQ7o5.png",
"type":"m38u",
"language":"Tamil",
"url": "http://45.77.66.224:1935/athavantv/live/playlist.m3u8",
"category": "Entertainment"
},

{
"name": "ABP Ananda",
"logo": "https://tv.releasemyad.com/images/logo/20160108044853abp-ananada.jpg",
"type":"m38u",
"language":"Hindi",
"url": "https://abp-i.akamaihd.net/hls/live/765530/abpananda/master.m3u8", "category":
"News"
},

{
"name": "ABP Ananda(720p)",
"logo": "https://tv.releasemyad.com/images/logo/20160108044853abp-ananada.jpg", "type":"m38u",
"url": "https://d3pnfn2zxtq6km.cloudfront.net/out/v1/c77a35d9d4f74371a3cf0f214a9eb8c0/index.m3u8", "category":
"News"
},

{
"name": "ABP Asmita(324p)",
"logo": "https://upload.wikimedia.org/wikipedia/en/4/42/ABP_Asmita_Logo.png",
"type":"m38u",
"language":"Gujrati",
"url": "http://abpasmita-lh.akamaihd.net:80/i/abpasmita_1@77821/master.m3u8",
"category": "News"
},

{
"name": "ABP Asmita(720p)",
"logo": "https://upload.wikimedia.org/wikipedia/en/4/42/ABP_Asmita_Logo.png",
"type":"m38u",
"language":"Gujrati",
"url": "https://abp-i.akamaihd.net/hls/live/765532/abpasmita/master.m3u8",
23
"category": "News"
},

{
"name": "ABP Asmita",
"logo": "https://upload.wikimedia.org/wikipedia/en/4/42/ABP_Asmita_Logo.png",
"type":"m38u",
"language":"Gujrati",
"url": "https://abpasmita-lh.akamaihd.net/i/abpasmita_1@77821/master.m3u8", "category":
"News"
},

{
"name": "ABP News(324p)",
"logo": "https://static.abplive.in/wp-content/themes/abp-hindi/images/logo/hindiLogoD.png",
"type":"m38u",
"language":"English",
"url": "http://hindiabp-lh.akamaihd.net/i/hindiabp1new_1@192103/master.m3u8",
"category": "News"
},

{
"name": "ABP Majha",
"logo": "https://upload.wikimedia.org/wikipedia/en/5/5a/ABP_Majha_Logo.png",
"type":"m38u",
"language":"Hindi",
"url": "https://abp-i.akamaihd.net/hls/live/765531/abpmajha/master.m3u8", "category":
"News"
},

{
"name": "ABP News(720p)",
"logo": "https://static.abplive.in/wp-content/themes/abp-hindi/images/logo/hindiLogoD.png",
"type":"m38u",
"language":"English",
"url": "https://abp-i.akamaihd.net/hls/live/765529/abphindi/master.m3u8", "category":
"News"
},
];

router.get('/', async (req,res) => {


if(req.Auth){
try { res.status('200').send(resJson_IndianChannelList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{

24
res.status('400').send('Auth fail');
}
});
module.exports = router;

11. Trending.js
const express = require('express');
const router = express.Router();

const resJson_trendingList = [
{
"name":"Godzilla vs Kong(Hindi audio)",
"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"Hindi",
"description":"Godzilla vs. Kong is a 2021 American monster film directed by Adam Wingard. A
sequel to Godzilla: King of the Monsters (2019) and Kong: Skull Island (2017), it is the fourth film
in Legendary's MonsterVerse. It is also the 36th film in the Godzilla franchise, the 12th film in the
King Kong franchise, and the fourth Godzilla film to be completely produced by a Hollywood studio.
The film stars Alexander Skarsgård, Millie Bobby Brown, Rebecca Hall, Brian Tyree Henry, Shun
Oguri, Eiza González, Julian Dennison, Lance Reddick, Kyle Chandler, and Demián Bichir. In the
film, Kong clashes with Godzilla as humans lure the ape into the Hollow Earth to retrieve a power
source for a weapon to stop Godzilla's mysterious rampages."
},
{
"name":"Blue call(720p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
xODA2MTA@._V1_FMjpg_UY682_.jpg
", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},
{
"name":"Panda Vs Aliens(720p)",
"logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"A group of aliens seek out to conquer new worlds and take particular notice of
Earth, after seeing satellite broadcasts of TV shows of a powerful panda, Pandy."
}
{
"name":"Blue call(360p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
25
"type":"m38u", "url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},
{
"name":"Godzilla vs Kong(Hindi audio)",
"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"Hindi",
"description":"Godzilla vs. Kong is a 2021 American monster film directed by Adam Wingard. A
sequel to Godzilla: King of the Monsters (2019) and Kong: Skull Island (2017), it is the fourth film
in Legendary's MonsterVerse. It is also the 36th film in the Godzilla franchise, the 12th film in the
King Kong franchise, and the fourth Godzilla film to be completely produced by a Hollywood studio.
The film stars Alexander Skarsgård, Millie Bobby Brown, Rebecca Hall, Brian Tyree Henry, Shun
Oguri, Eiza González, Julian Dennison, Lance Reddick, Kyle Chandler, and Demián Bichir. In the
film, Kong clashes with Godzilla as humans lure the ape into the Hollow Earth to retrieve a power
source for a weapon to stop Godzilla's mysterious rampages."
},
];

router.get('/', async (req,res) => {


if(req.Auth){
try {
res.status('200').send(resJson_trendingList);
} catch (error) {
res.status('500').send('Server error');
}}
else{
res.status('400').send('Auth fail');
}
});
module.exports = router;

12. NewArrivals.js
const express = require('express');
const router = express.Router();

const resJson_newArrivalsList = [
{
"name":"Godzilla vs Kong(Hindi audio)",
"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"Hindi",
"description":"Godzilla vs. Kong is a 2021 American monster film directed by Adam Wingard. A
sequel to Godzilla: King of the Monsters (2019) and Kong: Skull Island (2017), it is the fourth film in
Legendary's MonsterVerse. It is also the 36th film in the Godzilla franchise, the 12th film in the King

26
fourth Godzilla film to be completely produced by a Hollywood studio. The film stars Alexander
Skarsgård, Millie Bobby Brown, Rebecca Hall, Brian Tyree Henry, Shun Oguri, Eiza González, Julian
Dennison, Lance Reddick, Kyle Chandler, and Demián Bichir. In the film, Kong clashes with Godzilla
as humans lure the ape into the Hollow Earth to retrieve a power source for a weapon to stop Godzilla's
mysterious rampages."
},{
"name":"Blue call(720p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
xODA2MTA@._V1_FMjpg_UY682_.jpg",
"type":"m38u", "url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},
{
"name":"Panda Vs Aliens(720p)",
"logo":"https://upload.wikimedia.org/wikipedia/en/a/ac/PandavsAliens.jpg",
"type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"A group of aliens seek out to conquer new worlds and take particular notice of Earth, after
seeing satellite broadcasts of TV shows of a powerful panda, Pandy."
},{
"name":"Blue call(360p)",
"logo":"https://m.media-
amazon.com/images/M/MV5BZjk4NzlhMjYtMjhlZi00MjIzLWFkZjAtMzBhMWZhNjZhNDExXkEyXkFqcGdeQXVyMjI
xODA2MTA@._V1_FMjpg_UY682_.jpg",
"type":"m38u", "url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"English",
"description":"Haylee, a local EMT suffering from PTSD, spends her days making split second
decisions with lives that hang in the balance. One night on a routine call, she is faced with a moral
decision, taking matters into her own hands and mercy kills a young woman. Her decision opens a
pandora's box that leads Haylee to blur the lines of her job responsibilities and wanting to help those in
need. Now, falling deeper and deeper into a rabbit hole, she gets caught up in a world of underground
drugs and a sadistic killer who's made her his next victim."
},{
"name":"Godzilla vs Kong(Hindi audio)",
"logo":"https://images-na.ssl-images-amazon.com/images/I/81SAqNnNlfL._AC_SL1500_.jpg", "type":"m38u",
"url":"https://llvod.mxplay.com/video/4fffa9037b466b90e5cf0022f0fb7ebc/6/hls/h264_baseline.m3u8",
"language":"Hindi",
"description":"Godzilla vs. Kong is a 2021 American monster film directed by Adam Wingard. A
sequel to Godzilla: King of the Monsters (2019) and Kong: Skull Island (2017), it is the fourth film
in Legendary's MonsterVerse. It is also the 36th film in the Godzilla franchise, the 12th film in the
King Kong franchise, and the fourth Godzilla film to be completely produced by a Hollywood studio.
The film stars Alexander Skarsgård, Millie Bobby Brown, Rebecca Hall, Brian Tyree Henry, Shun
Oguri, Eiza González, Julian Dennison, Lance Reddick, Kyle Chandler, and Demián Bichir.

27
router.get('/', async (req,res) => {
if(req.Auth){
try { res.status('200').send(resJson_newArrivalsList);
} catch (error) {
res.status('500').send('Server error');
}

}
else{
res.status('400').send('Auth fail');
}

});

module.exports = router;

28
4.2. Backend Coding

4.2.1 Widgets

1. main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:playsar/presentation/bloc/channel_page_bloc/channelpage_bloc.dart';import
'package:playsar/presentation/bloc/home_page_bloc/homepage_bloc.dart';
import 'package:playsar/presentation/bloc/movie_list_page_bloc/movielistpage_bloc.dart';import
'package:playsar/presentation/bloc/series_list_page/serieslistpage_bloc.dart';

import 'presentation/pages/splash_screen.dart';import
'utils/constants.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget { const


MyApp({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MultiBlocProvider( providers:
[
BlocProvider(create: (_) => HomePageBloc()..add(GetHomePageData())),
BlocProvider(create: (_) => ChannelPageBloc()..add(GetChannelListData())),
BlocProvider(create: (_) => MovieListPageBloc()),
BlocProvider(create: (_) => SeriesListPageBloc()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.dark,
theme: ThemeData(
fontFamily: 'Mukta',
scaffoldBackgroundColor: backgroundColor,
buttonColor: darkBlueColor,
accentColor: whiteColor,
iconTheme: IconThemeData(color: whiteColor),
appBarTheme: AppBarTheme(backgroundColor: darkGreyColor),
bottomNavigationBarTheme:
BottomNavigationBarThemeData(backgroundColor: darkGreyColor),hintColor:
whiteColor,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.redAccent)
)
)
),
title: 'playsar',

29
home: SplashScreen(),
),
);
}
}

2. splash_screen.dart
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

import '../../utils/constants.dart';
import 'base_screen.dart';

class SplashScreen extends StatefulWidget {


SplashScreen({Key key}) : super(key: key);
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen>with
SingleTickerProviderStateMixin { AnimationController
_animationController;

@override
void initState() {
super.initState();
_animationController = AnimationController(vsync: this);
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: ListView(
shrinkWrap: true,
children: [
Lottie.asset(
'assets/images/splash_screen_animation_lottie_json.json', width:
width,
height: width,
fit: BoxFit.fill,
controller: _animationController, onLoaded: (composition) {
_animationController
..duration = composition.duration
..forward().whenComplete(() => Navigator.of(context)
.pushAndRemoveUntil(
MaterialPageRoute(builder: (context) {
return BaseScreen();
}), (route) => false));
}),
sized30, const
Text(
'playsar',

30
style: logoTextStyle,
textAlign: TextAlign.center,
)),
),
);
}
}

3. base_screen.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../../utils/constants.dart'; import


'channels/channel_page.dart';import
'home_page.dart';
import 'movies/movies_categories_page.dart';import
'series/series_categories_page.dart';

class BaseScreen extends StatefulWidget {


BaseScreen({Key key}) : super(key: key);

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

class _BaseScreenState extends State<BaseScreen> {var


currentScreen = 0;

static const _screenList = [


HomePage(),
ChannelPage(),
MoviesCategoriesPage(),
SeriesCategoriesPage()
];

void changeScreen(int newScreenValue) {


setState(() {
currentScreen = newScreenValue;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(child: _screenList.elementAt(currentScreen)),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(icon:
Icon( CupertinoIcons.home,
),
label: 'Home'), BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.tv,

31
),
label: 'Tv Channel'),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.film,
),
label: 'Movies'),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.tickets,
),
label: 'Series'),
],
backgroundColor: darkGreyColor,
currentIndex: currentScreen, onTap:
changeScreen, selectedItemColor:
darkBlueColor,
selectedLabelStyle: TextStyle(color: whiteColor),
unselectedItemColor: whiteColor,
);

4. home_screen.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/comming_soon/comming_soon.dart';import
'../widgets/comming_soon_banner.dart';

import '../../utils/constants.dart';
import '../bloc/home_page_bloc/homepage_bloc.dart';import
'../widgets/error_widget.dart';
import '../widgets/home_screen_banner.dart';
import '../widgets/horizontal_items_list.dart';

class HomePage extends StatefulWidget { const


HomePage({Key key}) : super(key: key);

@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {static
const titleGeneralError = 'Error occure';
static const titleNetworkError = 'No Internet Connection';

HomePageBloc _homePageBloc = HomePageBloc();

@override
void didChangeDependencies() {
super.didChangeDependencies();
_homePageBloc.add(GetHomePageData());
}
@override
void dispose() {
_homePageBloc.close();
super.dispose();
}
32
void retryFunction() async {
_homePageBloc.add(GetHomePageData());
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocBuilder<HomePageBloc, HomePageState>(bloc:
_homePageBloc,
builder: (context, state) {
if (state is HomePageLoadingState) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is HomePageLoadedState) {
return WidgetHomePageLoadedState(
newArrive: state.newArrivals, trendingList:
state.trendingList, featuredBanner:
state.featuredBanner,
commingSoonList: state.commingSoonList,
);
} else if (state is HomePageNoInternetState) {
return CustomeErrorWidget(
retryFunction: retryFunction,
errorTitle: titleNetworkError,
);
} else {
return CustomeErrorWidget(
retryFunction: retryFunction,
errorTitle: titleGeneralError,
);
},
),
);
}

class WidgetHomePageLoadedState extends StatelessWidget {static const


String titleNewArrive = 'New Arrive';
static const String titleTrending = 'Trending';
static const String appTitle = 'playsar';

const WidgetHomePageLoadedState({Key
key,
@required this.newArrive,
@required this.trendingList,
@required this.featuredBanner,
@required this.commingSoonList,
}) : super(key: key);

final List newArrive;


final List trendingList;
final featuredBanner;
final List<CommingSoon> commingSoonList;

@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return SafeArea(
33
child: NestedScrollView(
physics: NeverScrollableScrollPhysics(),
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
pinned: true,
floating: true,
centerTitle: true,
expandedHeight: size.height * 0.8,
title: const Text(
appTitle,
style: logoTextStyle,
),
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
background: HomeScreenBanner(
size: size,
featuredBanner: featuredBanner,
),
),
),
];
},
body: ListView(
shrinkWrap: true,
children: [
sized10,
HorizontalItemsList(listTitle: titleTrending, list: trendingList),
sized10,
HorizontalItemsList(listTitle: titleNewArrive, list: newArrive),
sized10,
Container( child:
Center(
child: const Text(
'Comming Soon',
style: commingSoonTitleStyle,
))),
sized20,
CommingSoonBanner(size: size, commingSoonList: commingSoonList),
sized20
],
)),
);
}

5. channel_page

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../utils/constants.dart';
import '../../bloc/channel_page_bloc/channelpage_bloc.dart';
import '../../widgets/channel_screen.dart';
import '../../widgets/error_widget.dart';

34
@override
_ChannelPageState createState() => _ChannelPageState();
}

class _ChannelPageState extends State<ChannelPage> {static


const titleGeneralError = 'Error occure';
static const titleNetworkError = 'No Internet Connection';

ChannelPageBloc _channelPageBloc;

@override
void didChangeDependencies() {
super.didChangeDependencies();
_channelPageBloc = ChannelPageBloc()..add(GetChannelListData());
}

@override
void dispose() {
_channelPageBloc.close();
super.dispose();
}

void retryFunction() async {


_channelPageBloc.add(GetChannelListData());
}

@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text(
'Tv Channel',
style: logoTextStyle,
),
centerTitle: true,
),
body: BlocConsumer<ChannelPageBloc, ChannelPageState>(bloc:
_channelPageBloc,
listener: (context, state) {},
builder: (context, state) {
if (state is ChannelPageLoadingState) {
return const Center(child: const CircularProgressIndicator());
} else if (state is ChannelPageLoadedState) {
return ChannelScreen(size: size, channelList: state.channelList);
} else if (state is ChannelPageNoInternetState) {
return CustomeErrorWidget(
retryFunction: retryFunction,
errorTitle: titleNetworkError,
);
} else {
return CustomeErrorWidget(
retryFunction: retryFunction,
errorTitle: titleGeneralError,
);},

35
6. channel_page

import 'package:flutter/material.dart';
import 'package:playsar/presentation/pages/movies/movies_list_page.dart';

import '../../../data/movies/movies_categories.dart';
import '../../../utils/constants.dart';
import '../../widgets/categories_widget.dart';

class MoviesCategoriesPage extends StatefulWidget {


const MoviesCategoriesPage({Key key}) : super(key: key);

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

class _MoviesCategoriesPageState extends State<MoviesCategoriesPage> {


var movieCateroiesList = movieCategories;

@override
void initState() {
super.initState();
}

void onSearchBarValueChangeFunction(String searchText) {


final searchedChannels = movieCategories.where((category) {
final categoryNameToLowerCase = category.categoryName.toLowerCase();final
searchTextToLowerCase = searchText.toLowerCase();

return categoryNameToLowerCase.contains(searchTextToLowerCase);
}).toList();

setState(() {
this.movieCateroiesList = searchedChannels;
});
}

@override
Widget build(BuildContext context) {
return Scaffold( appBar:
AppBar( centerTitle:
true, title: const Text(
'Movies Categories',
style: logoTextStyle,
),
),
body: CategoriesWidget(
onSearchBarValueChangeFunction: onSearchBarValueChangeFunction,categoriesList:
movieCateroiesList,
onTapNavigate: (categoryUrl, categoryName) {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return MovieListPage(
categoryUrl: categoryUrl, categoryName: categoryName);
}));
},
));

36
7. movies_category_page.dart

import 'package:flutter/material.dart';

import 'package:playsar/presentation/pages/movies/movies_list_page.dart';

import '../../../data/movies/movies_categories.dart';import '../../../utils/constants.dart';

import '../../widgets/categories_widget.dart';

class MoviesCategoriesPage extends StatefulWidget {

const MoviesCategoriesPage({Key key}) : super(key: key);

@override

_MoviesCategoriesPageState createState() => _MoviesCategoriesPageState();

class _MoviesCategoriesPageState extends State<MoviesCategoriesPage> {var movieCateroiesList =

movieCategories;

@override

void initState() {

super.initState();

void onSearchBarValueChangeFunction(String searchText) {

final searchedChannels = movieCategories.where((category) {

final categoryNameToLowerCase = category.categoryName.toLowerCase();final

searchTextToLowerCase = searchText.toLowerCase();

return categoryNameToLowerCase.contains(searchTextToLowerCase);

}).toList();

37
setState(() {

this.movieCateroiesList = searchedChannels;

});

@override

Widget build(BuildContext context) {return Scaffold(

appBar: AppBar( centerTitle:

true,title: const Text(

'Movies Categories', style:

logoTextStyle,

),

),

body: CategoriesWidget(

onSearchBarValueChangeFunction: onSearchBarValueChangeFunction,categoriesList:

movieCateroiesList,

onTapNavigate: (categoryUrl, categoryName) {

Navigator.of(context).push(MaterialPageRoute(builder: (context)
{

return MovieListPage(

categoryUrl: categoryUrl, categoryName: categoryName);

}));

},

));

8. series_category_page.dart

import 'package:flutter/material.dart';
38
import '../../../data/series/series_categories.dart';import '../../../utils/constants.dart';

import '../../widgets/categories_widget.dart';import

'series_list_page.dart';

class SeriesCategoriesPage extends StatefulWidget {

const SeriesCategoriesPage({Key key}) : super(key: key);

@override

_SeriesCategoriesPageState createState() => _SeriesCategoriesPageState();

class _SeriesCategoriesPageState extends State<SeriesCategoriesPage> {var seriesCateroiesList =

seriesCategories;

@override

void initState() {

super.initState();

void onSearchBarValueChangeFunction(String searchText) {

final searchedChannels = seriesCategories.where((category) {

final categoryNameToLowerCase = category.categoryName.toLowerCase();final

searchTextToLowerCase = searchText.toLowerCase();

return categoryNameToLowerCase.contains(searchTextToLowerCase);

}).toList();

setState(() {

this.seriesCateroiesList = searchedChannels;

});

39
@override

Widget build(BuildContext context) {return Scaffold(

appBar: AppBar( centerTitle:

true,title: const Text(

'Series Categories', style:

logoTextStyle,

),

),

body: CategoriesWidget(

onSearchBarValueChangeFunction: onSearchBarValueChangeFunction,categoriesList:

seriesCateroiesList,

onTapNavigate: (categoryUrl, categoryName) {

Navigator.of(context).push(MaterialPageRoute(builder: (context)
{

return SeriesListPage(

categoryUrl: categoryUrl, categoryName: categoryName);

}));

},

));

9. app_widgets.dart

//@dart=2.9
import 'package:cached_network_image/cached_network_image.dart';import
'package:flutter/material.dart';

class AppWidget {

static String defaultImageURL = "https://i1.wp.com/lanecdr.org/wp-


content/uploads/2019/08/placeholder.png?w=1200&ssl=1";

static Widget imageView(String url,


{double height,
double width,

40
BoxFit fit,
Color backgroundColor,
bool circle,
String error}) {
return Builder(builder: (ctx) { if
(url == null || url.isEmpty) {if
(circle != null && circle) {
return ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(100)),child:
Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
));
}
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
);
} else {
if (circle != null && circle) {
return ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(100)),child :
CachedNetworkImage(
imageUrl: url ?? defaultImageURL,
width: width,
height: height,
fit: fit,
placeholder: (context,url){
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
);
},
errorWidget: (context, url, error) {
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
41
width: width,
height: height,
),
),
);
},
),
);
}
return CachedNetworkImage(
imageUrl: url ?? defaultImageURL,
width: width,
height: height,
fit: fit,
placeholder: (context,url){
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
error ?? "assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
);
},
errorWidget: (context, url, error) {
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
);
},
);
}
})

42
static Widget profileImageView(String url,
{double height,
double width,
BoxFit fit,
Color backgroundColor,
bool circle,
String error}) {
return Builder(builder: (ctx) { if
(url == null || url.isEmpty) {if
(circle != null && circle) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
"assets/images/placeholder.jpeg",
fit: BoxFit.fill,
width: width,
height: height,
),
),
));
}
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
);
} else {
if (circle != null && circle)
{return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: CachedNetworkImage(
imageUrl: url ?? defaultImageURL,
width: width,
height: height,
fit: fit,
placeholder: (context,url){
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
);
},
errorWidget: (context, url, error) {
return Container(
43
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",fit:
BoxFit.fill,
width: width,
height: height,
),
),
);
},
),
);
}
return CachedNetworkImage(
imageUrl: url ?? defaultImageURL,
width: width,
height: height,

44
fit: fit,
placeholder: (context,url){
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
"assets/images/placeholder.jpeg",
fit: BoxFit.fill,
width: width,
height: height,
),
),
);
},
errorWidget: (context, url, error) {
return Container(
color: backgroundColor ?? Colors.transparent,
child: Center(
child: Image.asset(
'assets/images/placeholder.jpeg',
fit: BoxFit.fill,
width: width,
height: height,
),
),
);
},
}
);
})
;
}}

10. categories_widgets.dart

import 'package:flutter/material.dart';
import '../../utils/constants.dart';import
'Grid_Card.dart';
import 'search_bar.dart';

class CategoriesWidget extends StatelessWidget {final Function


onSearchBarValueChangeFunction;final Function(String, String)
onTapNavigate; final List categoriesList;
const CategoriesWidget(
{Key key,
@required this.onSearchBarValueChangeFunction,@required
this.categoriesList,
@required this.onTapNavigate})
: super(key: key);
@override
Widget build(BuildContext context) {

45
return ListView(
children: [
sized10,
SearchBar(
searchHint: searchCategories,
onchangeFunction: onSearchBarValueChangeFunction,
),
sized10,
GridView.builder(
physics: NeverScrollableScrollPhysics(),shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: categoriesList.length,itemBuilder: (context,
index) {
return GestureDetector(
onTap: () =>
onTapNavigate(categoriesList[index].categoryUrl,
categoriesList[index].categoryName),child: GridCard(
name: categoriesList[index].categoryName,
logoUrl: categoriesList[index].categoryLogo,
),
);
}),
],
);
}
}

11. channel_card.dart

import 'package:flutter/material.dart'; class ChannelCard extends

StatelessWidget {
final String channelName;final String
channelLogo;final Size size;
const ChannelCard(
{Key key,
@required this.channelName,@required
this.channelLogo,@required this.size})
: super(key: key);

46
Widget build(BuildContext context) {
return Container(height:
100.0,
width: 100.0, child:
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Container( decoration:
BoxDecoration(
borderRadius: BorderRadius.circular(20.0),image:
DecorationImage(
image: NetworkImage(channelLogo), fit: BoxFit.fill)),
),
),
],
),
);
}
}

12. channel_screen.dart

import 'package:flutter/material.dart';
import 'package:playsar/presentation/widgets/Grid_Card.dart';

import '../../data/channels/channel.dart';import
'../../utils/constants.dart'; import
'../pages/view_media_page.dart'; import 'channel_card.dart';
import 'search_bar.dart';

class ChannelScreen extends StatefulWidget {


const ChannelScreen({
Key key,
@required this.size, @required
this.channelList,
}) : super(key: key);
final Size size;
final List<Channel> channelList;
@override
_ChannelScreenState createState() => _ChannelScreenState();
}

class _ChannelScreenState extends State<ChannelScreen> {List<Channel>


channels = [];
47
void initState() {
super.initState();
channels = widget.channelList;
}

void onSearchBarValueChangeFunction(String searchText) {


final searchedChannels = widget.channelList.where((channel) {final
channelNameToLowerCase = channel.name.toLowerCase(); final
searchTextToLowerCase = searchText.toLowerCase();

return channelNameToLowerCase.contains(searchTextToLowerCase);
}).toList();

setState(() {
this.channels = searchedChannels;
});
}

@override
Widget build(BuildContext context) {return
SingleChildScrollView(
child: Column(
children: [
sized10,
SearchBar(
searchHint: searchChannels,
onchangeFunction: onSearchBarValueChangeFunction,
),
sized10,
Padding(
padding: const EdgeInsets.all(20.0),child:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2,
crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0),
physics: NeverScrollableScrollPhysics(),shrinkWrap: true,
itemCount: channels.length, itemBuilder: (context,
index) {
return InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context)
{
channels[index].url);
}),

48
return ViewMediaPage(source:
}));
},
child: GridCard(
name:
channels[ind
ex].name,
logoUrl:
channels[ind
ex].logo,
));

],
),
);
}

49
13. coming_soon_banner.dart

import 'package:flutter/material.dart';
import 'package:playsar/data/comming_soon/comming_soon.dart';

class CommingSoonBanner extends StatelessWidget {final Size size;


final List<CommingSoon> commingSoonList;const
CommingSoonBanner(
{Key key, @required this.size, @required this.commingSoonList})
: super(key: key);

@override
Widget build(BuildContext context) {return
Container(
height: size.height * 0.25,
child: Center(
child: ListView.builder( scrollDirection:
Axis.horizontal, physics:
BouncingScrollPhysics(), itemCount:
commingSoonList.length,itemBuilder: (context,
index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal:10.0),width: size.width * 0.8,
height: size.height * 0.25,child: Center(
child: Text(commingSoonList[index].name,
style: const TextStyle(
color: Colors.white, fontWeight:
FontWeight.w600,fontSize: 24.0)),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),image:
DecorationImage(
image: NetworkImage(commingSoonList[index].logo),fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.2), BlendMode.dstATop),
),
),
);
}),
),

50
14. grid_card.dart

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:playsar/presentation/widgets/app_widget.dart';import

'../../utils/constants.dart';

class GridCard extends StatelessWidget {final


String name;

final String logoUrl;

const GridCard(
{Key key,
@required this.name,

@required this.logoUrl})
: super(key: key);

@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),

gradient:
LinearGradient(
begin: Alignment.topLeft, end:
Alignment.bottomRight,
colors: [darkBlueColor , darkGreyColor]),
),
child: Column(children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0),
),
),
child: AppWidget.imageView(
logoUrl,
fit: BoxFit.fill,
),
),
),
sized5,
RichText(
text: TextSpan(
text: name,
style: listTitleStyle

51
sized5
]),
);
}

15. home_screen_banner.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../../utils/constants.dart';
import '../pages/view_media_page.dart';

class HomeScreenBanner extends StatelessWidget {static


const String watch = 'Watch';
final Size size;
final featuredBanner;
const HomeScreenBanner({
Key key,
@required this.size,
@required this.featuredBanner,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container(
height: size.height * 0.7,
width: double.infinity,
child: Stack(
children: [
Container(
height: size.height,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(featuredBanner.logo),fit:
BoxFit.fill,
)),),
Positioned(
left: 0.0,
top: size.height * 0.7,
child: Container(
width: size.width,
child: Center(
child: GestureDetector(
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) { return
ViewMediaPage(source: featuredBanner.url);
}));},
child: Container(
decoration: BoxDecoration(
color: whiteColor, border:
Border.all(
color: Colors.black, style:
BorderStyle.solid,
52
),
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(.7),
blurRadius: 3.0,
spreadRadius: 0.5)
]),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
const Padding(
padding: const EdgeInsets.only(left: 10.0),
child: const Icon(
CupertinoIcons.play,color:
Colors.black,
),
),
const Padding(
padding: const EdgeInsets.only(right: 10.0),
child: const Text(
watch,
style: TextStyle(fontWeight: FontWeight.w700),
),
),
],
),
),
),
)),
],
),
);
}
}

16. horizontal_items_list.dart

import 'package:flutter/material.dart';

import '../../utils/constants.dart';
import '../pages/view_media_page.dart';

class HorizontalItemsList extends StatelessWidget {final


String listTitle;
final List list;
const HorizontalItemsList(
{Key key, @required this.listTitle, @required this.list})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),child:
Column(
53
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, children:
[
Container(
child: Text(
listTitle,
style: listTitleStyle,
),
),
Container(
child: Text(
'(${list.length})',
style: listTitleStyle,
),
),
],
),
Container(
margin: const EdgeInsets.symmetric(vertical: 5.0),
height: 170.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: ListView.builder(
shrinkWrap: true, scrollDirection:
Axis.horizontal,itemCount:
list.length, itemBuilder: (context,
index) { return GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) { return
ViewMediaPage(source: list[index].url);
}));
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 5.0),height:
150.0,
width: 100.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(list[index].logo),
fit: BoxFit.contain,
),
borderRadius: BorderRadius.all(Radius.circular(10.0))),
),
);
}),

17. list_screen.dart

import 'package:flutter/material.dart';

54
import '../../utils/constants.dart';
import 'Grid_Card.dart';
import 'search_bar.dart';

class ListScreen extends StatefulWidget {


final List list;
final Function(Object) navigationFunction;
final searchHint;
const ListScreen({
Key key,
@required this.list,
@required this.navigationFunction,
@required this.searchHint
}) : super(key: key);

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

class _ListScreenState extends State<ListScreen> {List


itemList = [];
@override
void initState() {
super.initState();
itemList = widget.list;
}

void onSearchBarValueChangeFunction(String searchText) {final


searched = widget.list.where((item) {
final listItemNameToLowerCase = item.name.toLowerCase();final
searchTextToLowerCase = searchText.toLowerCase();

return listItemNameToLowerCase.contains(searchTextToLowerCase);
}).toList();

setState(() {
this.itemList = searched;
});
}

@override
Widget build(BuildContext context) {
return CustomScrollView(slivers: [
const SliverToBoxAdapter(
child: SizedBox(
height: 10.0,
),
),
SliverToBoxAdapter(
child: SearchBar(
searchHint: widget.searchHint,
onchangeFunction: onSearchBarValueChangeFunction)),const
SliverToBoxAdapter(
child: SizedBox(
height: 10.0,
),
),

55
delegate: SliverChildBuilderDelegate(
(context, index) {
return GestureDetector(
onTap: () => widget.navigationFunction(itemList[index]),
child: GridCard(
name: itemList[index].name,
logoUrl: itemList[index].logo,
),
);
},
childCount: itemList.length,
),
),
]);
}
}

18. search_bar.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../../utils/constants.dart';

class SearchBar extends StatefulWidget {final


String searchHint;
final Function onchangeFunction;
const SearchBar({
Key key,
@required this.searchHint, @required
this.onchangeFunction,
}) : super(key: key);
@override
_SearchBarState createState() => _SearchBarState();
}
class _SearchBarState extends State<SearchBar> {
TextEditingController textEditingController;

@override
void initState() {
super.initState();
textEditingController = TextEditingController();
}
@override
void dispose() { textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container( width:
double.infinity,height:
70.0,
margin: const EdgeInsets.symmetric(horizontal: 10.0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(.05),
56
borderRadius: BorderRadius.circular(50.0),
),
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),child:
TextField(
enableSuggestions: true,
controller: textEditingController,
cursorColor: darkBlueColor,
style: TextStyle(color: Colors.white.withOpacity(.8)),
decoration: InputDecoration(
focusColor: darkBlueColor,
border: InputBorder.none,
hintText: widget.searchHint,
prefixIcon: InkWell(
child: Icon(CupertinoIcons.search, color: darkBlueColor),
onTap: () {
FocusScope.of(context).unfocus();
},
),
suffixIcon: textEditingController.text.isNotEmpty
? InkWell(
child: Icon(
CupertinoIcons.clear,
color: Colors.redAccent,
),
onTap: () {
textEditingController.clear();
widget.onchangeFunction('');
FocusScope.of(context).requestFocus(FocusNode());
},
)
: null),
onChanged: widget.onchangeFunction,
),
);
}
}

19. series_season_display_card.dart

import 'package:flutter/material.dart';
import 'package:playsar/data/series/episode.dart';

import '../../data/series/seasons.dart';
import '../../utils/constants.dart';

class SeriesSeasonDisplayCard extends StatelessWidget {final


Seasons seasons;
final Episode episode;
const SeriesSeasonDisplayCard({
this.seasons,
this.episode,
});
@override
Widget build(BuildContext context) {
return Container( color:
darkGreyColor,

57
Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
image: DecorationImage(
image: NetworkImage(seasons!=null ? seasons.seasonLogo: episode.episodeLogo),
fit: BoxFit.cover)),
),
const SizedBox(
width: 10.0,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
seasons!=null ? seasons.seasonName: episode.episodeName,style:
TextStyle(
color: whiteColor,
fontWeight: FontWeight.w700,
fontSize: 26.0),
),
Text(
seasons!=null ? seasons.seasonDescription: episode.episodeDescription,style:
TextStyle(
color: Colors.white54,
fontWeight: FontWeight.w300,
fontSize: 20.0),
),
],
),
],
),
);
}
}

20. widget_information_box.dart

import 'package:flutter/material.dart';

import '../../utils/constants.dart';

class WidgetInformationBox extends StatelessWidget {const


WidgetInformationBox({
Key key,
@required this.width,
@required this.text, @required
this.title,
}) : super(key: key);
58
final String text;

@override
Widget build(BuildContext context) {return
Container(
width: width,
padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal:10.0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.05),
),
child: RichText( text:
TextSpan(
style: const TextStyle(fontSize:
15.0, color: whiteColor,
),
children: <TextSpan>[
TextSpan(text: title),TextSpan(
text: text,
style: const TextStyle( fontWeight:
FontWeight.bold,
),
),
],
),
),
);
}
}

59
4.3. Data

1. Channel & Language:

import 'dart:convert';

import 'package:flutter/foundation.dart';import

'language.dart';

class Channel {
final String name;
final String logo;
final String url;
final String category;

const Channel({ @required


this.name, @required
this.logo, @required
this.url, @required
this.category,

});

Channel copyWith({
String name, String
logo,
String url,
String category,
List<Language> languages,
}) {
return Channel(
name: name ?? this.name,
logo: logo ?? this.logo,
url: url ?? this.url,
category: category ?? this.category,

);
}

Map<String, dynamic> toMap() {


return {
'name': name,
'logo': logo,
'url': url,
'category': category,

};
}

factory Channel.fromMap(Map<String, dynamic> map) {


return Channel(
name: map['name'] as String,
logo: map['logo'] as String,
60
url: map['url'] as String,
category: map['category'] as String,

);
}

String toJson() => json.encode(toMap());

factory Channel.fromJson(String source) =>


Channel.fromMap(json.decode(source));

@override
String toString() {
return 'Channel(name: $name, logo: $logo, url: $url, category: $category)';
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Channel &&


other.name == name &&
other.logo == logo &&
other.url == url &&
other.category == category;
}

@override
int get hashCode {
return name.hashCode ^
logo.hashCode ^
url.hashCode ^
category.hashCode;
}
}

import 'dart:convert';

import 'package:flutter/cupertino.dart';

class Language {
final String code;
final String name;
const Language({
@required this.code,
@required this.name,
});
Language copyWith({
String code,
String name,
}) {
return Language(
code: code ?? this.code,
name: name ?? this.name,
);
}

Map<String, dynamic> toMap() {


return {
61
factory Language.fromMap(Map<String, dynamic> map) {
return Language(
code: map['code'],
name: map['name'],
);
}

String toJson() => json.encode(toMap());

factory Language.fromJson(String source) => Language.fromMap(json.decode(source));

@override
String toString() => 'Language(code: $code, name: $name)';

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Language &&


other.code == code &&
other.name == name;
}

@override
int get hashCode => code.hashCode ^ name.hashCode;
}

2. comming_soon.dart
import 'dart:convert';

class CommingSoon {
final String name;
final String logo;
final String releaseDate;

const CommingSoon(
this.name,
this.logo,
this.releaseDate,
);

CommingSoon copyWith({
String name,
String logo,
String releaseDate,
}) {
return CommingSoon(
name ?? this.name,
logo ?? this.logo,
releaseDate ?? this.releaseDate,
);
}

Map<String, dynamic> toMap() {


return {
'name': name,
factory CommingSoon.fromMap(Map<String, dynamic> map) {
return CommingSoon(
map['name'],
62
map['logo'],
map['releaseDate'],
);
}

String toJson() => json.encode(toMap());

factory CommingSoon.fromJson(String source) => CommingSoon.fromMap(json.decode(source));@override


String toString() => 'CommingSoon(name: $name, logo: $logo, releaseDate: $releaseDate)';

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is CommingSoon &&


other.name == name && other.logo
== logo && other.releaseDate ==
releaseDate;
}

@override
int get hashCode => name.hashCode ^ logo.hashCode ^ releaseDate.hashCode;
}

3. Movies
import 'dart:convert';

import 'package:flutter/cupertino.dart';

class Movie {
final String name;
final String logo;
final String url;
final String language;
final String description;
const Movie({
@required this.name,
@required this.logo,
@required this.url,
@required this.language,
@required this.description,
});

Movie copyWith({
String name,
String logo,
String url,
String language,
String description,
}) {
return Movie(
name: name ?? this.name,
logo: logo ?? this.logo,
url: url ?? this.url,

63
language: language ?? this.language,
description: description ?? this.description,
);
}

Map<String, dynamic> toMap() {


return {
'name': name,
'logo': logo,
'url': url,
'language': language,
'description': description,
};
}

factory Movie.fromMap(Map<String, dynamic> map) {


return Movie(
name: map['name'],
logo: map['logo'],
url: map['url'],
language: map['language'],
description: map['description'],
);
}

String toJson() => json.encode(toMap());

factory Movie.fromJson(String source) => Movie.fromMap(json.decode(source));@override


String toString() {
return 'Movie(name: $name, logo: $logo, url: $url, language: $language, description: $description)';
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Movie &&


other.name == name &&
other.logo == logo &&
other.url == url &&
other.language == language &&
other.description == description;
}

@override
int get hashCode {
return name.hashCode ^
logo.hashCode ^
url.hashCode ^
language.hashCode ^
description.hashCode;
}
}

import 'package:flutter/foundation.dart';

class MoviesCategories {
64
final String categoryName;final String

categoryUrl; final String

categoryLogo;const

MoviesCategories(

{@required this.categoryUrl, @required

this.categoryLogo, @required

this.categoryName});

const List<MoviesCategories> movieCategories = const [MoviesCategories(

categoryName: 'Action', categoryUrl:

'actionMovies',categoryLogo:

'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4
NwjIBKuOMjVi4ou8UR'),

MoviesCategories(

categoryName: 'Adventure', categoryUrl:

'adventureMovies',categoryLogo:

'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4
NwjIBKuOMjVi4ou8UR'),

MoviesCategories( categoryName:

'Animated',

categoryUrl: 'animatedMovies',

categoryLogo:

'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4
NwjIBKuOMjVi4ou8UR'),

MoviesCategories( categoryName:

'Comedies',

categoryUrl: 'comediesMovies',categoryLogo:

65
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories( categoryName:

'Dramas',

categoryUrl: 'dramasMovies',

categoryLogo:

'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories( categoryName:

'Horror',

categoryUrl: 'horrorMovies',

categoryLogo:

'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories(

categoryName: 'Musical', categoryUrl:

'musicalMovies',categoryLogo:

'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories( categoryName: 'Other',

categoryUrl: 'otherMovies',

categoryLogo:

'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories( categoryName:

'RealLife',

categoryUrl: 'reallifeMovies',

categoryLogo:

66
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

MoviesCategories( categoryName:

'Romantic',

categoryUrl: 'romanticMovies',categoryLogo:

'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),

];

4. Series
import 'dart:convert';

import 'package:flutter/cupertino.dart';

class Episode {
final String episodeName;
final String episodeDescription;
final String episodeUrl;
final String episodeLogo;
const Episode({
@required this.episodeName,
@required this.episodeDescription,
@required this.episodeUrl, @required
this.episodeLogo,
});

Episode copyWith({
String episodeName,
String episodeDescription,
String episodeUrl,
String episodeLogo,
}) {
return Episode(
episodeName: episodeName ?? this.episodeName, episodeDescription:
episodeDescription ?? this.episodeDescription,episodeUrl: episodeUrl ??
this.episodeUrl,
episodeLogo: episodeLogo ?? this.episodeLogo,
);
}

Map<String, dynamic> toMap() {


return {
'episodeName': episodeName,
'episodeDescription': episodeDescription,
'episodeUrl': episodeUrl,

67
'episodeLogo': episodeLogo,
};
}

factory Episode.fromMap(Map<String, dynamic> map) {


return Episode(
episodeName: map['episodeName'],
episodeDescription: map['episodeDescription'],
episodeUrl: map['episodeUrl'],
episodeLogo: map['episodeLogo'],
);
}
String toJson() => json.encode(toMap());

factory Episode.fromJson(String source) => Episode.fromMap(json.decode(source));

@override
String toString() {
return 'Episode(episodeName: $episodeName, episodeDescription: $episodeDescription,
episodeUrl: $episodeUrl, episodeLogo: $episodeLogo)';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Episode &&


other.episodeName == episodeName &&
other.episodeDescription == episodeDescription &&
other.episodeUrl == episodeUrl && other.episodeLogo
== episodeLogo;
}

@override
int get hashCode {
return episodeName.hashCode ^
episodeDescription.hashCode ^
episodeUrl.hashCode ^
episodeLogo.hashCode;
}
}
//seasons

import 'dart:convert';
import 'package:flutter/foundation.dart';

import 'package:playsar/data/series/episode.dart';class

Seasons {
final String seasonName;
final String seasonDescription;
final String seasonLogo;
final List<Episode> episodes;
const Seasons({
@required this.seasonName,
@required this.seasonDescription,
@required this.seasonLogo,
@required this.episodes,
68
});

Seasons copyWith({
String seasonName,
String seasonDescription,
String seasonLogo,
List<Episode> episodes,
}) {
return Seasons(
seasonName: seasonName ?? this.seasonName, seasonDescription:
seasonDescription ?? this.seasonDescription,seasonLogo: seasonLogo ??
this.seasonLogo,
episodes: episodes ?? this.episodes,
);
}

Map<String, dynamic> toMap() {


return {
'seasonName': seasonName,
'seasonDescription': seasonDescription,
'seasonLogo': seasonLogo,
'episodes': episodes?.map((x) => x.toMap())?.toList(),
};
}

factory Seasons.fromMap(Map<String, dynamic> map) {


return Seasons(
seasonName: map['seasonName'],
seasonDescription: map['seasonDescription'],
seasonLogo: map['seasonLogo'],
episodes: List<Episode>.from(map['episodes']?.map((x) => Episode.fromMap(x))),
);
}

String toJson() => json.encode(toMap());

factory Seasons.fromJson(String source) => Seasons.fromMap(json.decode(source));@override


String toString() {
return 'Seasons(seasonName: $seasonName, seasonDescription: $seasonDescription,
seasonLogo: $seasonLogo, episodes: $episodes)';
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Seasons &&


other.seasonName == seasonName &&
other.seasonDescription == seasonDescription &&
other.seasonLogo == seasonLogo &&
listEquals(other.episodes, episodes);
}

@override
int get hashCode {
return seasonName.hashCode ^
seasonDescription.hashCode ^
seasonLogo.hashCode ^
episodes.hashCode;
69
}
}

import 'dart:convert';

import 'package:flutter/foundation.dart';

import 'seasons.dart';

class Series {
final String name;
final String logo;
final List<Seasons> seasons;
final String language;
final String description;
Series({
@required this.name,
@required this.logo,
@required this.seasons,
@required this.language,
@required this.description,
});

Series copyWith({
String name,
String logo,
List<Seasons> seasons,
String language,
String description,
}) {
return Series(
name: name ?? this.name,
logo: logo ?? this.logo,
seasons: seasons ?? this.seasons, language:
language ?? this.language, description:
description ?? this.description,
);
}

Map<String, dynamic> toMap() {


return {
'name': name,
'logo': logo,
'seasons': seasons?.map((x) => x.toMap())?.toList(),
'language': language,
'description': description,
};
}

factory Series.fromMap(Map<String, dynamic> map) {


return Series(
name: map['name'],
logo: map['logo'],
seasons: List<Seasons>.from(map['seasons']?.map((x) => Seasons.fromMap(x))),language:
map['language'],
description: map['description'],
);
}

70
factory Series.fromJson(String source) => Series.fromMap(json.decode(source));

@override
String toString() {
return 'Series(name: $name, logo: $logo, seasons: $seasons, language: $language, description:
$description)';
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Series &&


other.name == name &&
other.logo == logo &&
listEquals(other.seasons, seasons) &&
other.language == language &&
other.description == description;
}

@override
int get hashCode {
return name.hashCode ^
logo.hashCode ^
seasons.hashCode ^
language.hashCode ^
description.hashCode;
}
}

import 'package:flutter/foundation.dart';

class SeriesCategories { final


String categoryName;final
String categoryUrl; final
String categoryLogo; const
SeriesCategories(
{@required this.categoryUrl,
@required this.categoryLogo,
@required this.categoryName});
}

const List<SeriesCategories> seriesCategories = const [SeriesCategories(


categoryName: 'Action',
categoryUrl: 'actionSeries',
categoryLogo:

'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4NwjIBKuOMjVi
4ou8UR'),
SeriesCategories( categoryName:
'Adventure', categoryUrl:
'adventureSeries',categoryLogo:
'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4NwjIBKuOMjVi
4ou8UR'),
SeriesCategories( categoryName:
'Animated', categoryUrl:
'animatedSeries',categoryLogo:

71
'https://t3.gstatic.com/images?q=tbn:ANd9GcQzBPeJBL1nrbE44py9eA0PFWzRQjQlW4NwjIBKuOMjVi
4ou8UR'),
SeriesCategories( categoryName:
'Comedies', categoryUrl:
'comediesSeries',categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories( categoryName:
'Dramas', categoryUrl:
'dramasSeries',categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories(
categoryName: 'Horror',
categoryUrl: 'horrorSeries',
categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories( categoryName:
'Musical', categoryUrl:
'musicalSeries',categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories(
categoryName: 'Other',
categoryUrl: 'otherSeries',
categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories(
categoryName: 'RealLife',
categoryUrl: 'reallifeSeries',
categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
SeriesCategories( categoryName:
'Romantic', categoryUrl:
'romanticSeries',categoryLogo:
'https://images.unsplash.com/photo-1509248961158-
e54f6934749c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-
1.2.1&auto=format&fit=crop&q=80'),
];

72
4.4. Domain
network_repository.dart:

import 'dart:convert';

import 'package:http/http.dart' as http;

import '../../data/channels/channel.dart';
import '../../data/comming_soon/comming_soon.dart';import
'../../data/movies/movies.dart';
import '../../data/series/series.dart'; import
'../../utils/network_constants.dart';

class NetworkRepo {
static final client = http.Client();
static const Map<String, String> tokenData = { "Content-
type": "application/x-www-form-urlencoded",
"Authorization": NetworkConstants.token
};

/// This is for channel section


//get indian channel list
Future<List<Channel>> indianChannelList() async {
List<Channel> channelList = [];
try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}indianChannelList'),
headers: tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((_mapElement) {
channelList.add(Channel.fromMap(_mapElement));
});
return channelList;
} catch (e) {
print(e.toString());
throw (e);
}
}
///this is for home page section
//get featured banner
Future<Movie> getFeaturedBanner() async {try
{
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}featuredBanner'), headers:
tokenData);

final movie = Movie.fromJson(response.body);

return movie;
} catch (e) {
throw (e);
}

}//get trending list


Future<List<Movie>> trendingList() async {
73
List<Movie> trendingList = [];
try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}trendingList'),
headers: tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((_mapElement) {
trendingList.add(Movie.fromMap(_mapElement));
});

return trendingList;
} catch (e) {
throw (e);
}
}

//new arrivals list


Future<List<Movie>> newArrivalList() async {
List<Movie> newArrivals = [];
try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}newarrivals'),
headers: tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((_mapElement) {
newArrivals.add(Movie.fromMap(_mapElement));
});

return newArrivals;
} catch (e) {
throw (e);
}
}

//comming_soon
Future<List<CommingSoon>> getCommingSoonList() async {
List<CommingSoon> commingsoonList = [];

try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}commingsoon'), headers:
tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((commingsoonElement) {
commingsoonList.add(CommingSoon.fromMap(commingsoonElement));
});

return commingsoonList;
} catch (e) {
print(e.toString());
throw (e);
}
}

74
List<Movie> movieList = [];
try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}$categoryUrl'),
headers: tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((_mapElement) {
movieList.add(Movie.fromMap(_mapElement));
});
return movieList;
} catch (e) {
throw (e);
}
}

///series page

//get series list according to category


Future<List<Series>> getSeriesCategoryList(String categoryUrl) async {
List<Series> seriesList = [];
try {
final response = await client.get(
Uri.parse('${NetworkConstants.baseUrl}$categoryUrl'),
headers: tokenData);
List parsed = jsonDecode(response.body).cast<Map<String, dynamic>>();

parsed.forEach((_mapElement) { seriesList.add(Series.fromMap(_mapElement));
});
return seriesList;
} catch (e) {
throw (e);
}
}
}

4.5 .Bloc

1. home_page_bloc

import 'dart:async';
import 'dart:io';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';

import '../../../data/comming_soon/comming_soon.dart';
import '../../../data/movies/movies.dart';
import '../../../domain/repositories/network_repo.dart';

75
class HomePageBloc extends Bloc<HomePageEvent, HomePageState> {
static final networkRepo = NetworkRepo();
HomePageBloc() : super(HomePageLoadingState());

@override
Stream<HomePageState> mapEventToState(
HomePageEvent event,
) async* {
if (event is GetHomePageData) {
yield HomePageLoadingState();try
{
// print(DateTime.now().toString());
// final value = await Future.wait(
// [networkRepo.trendingList(), networkRepo.getFeaturedBanner(),networkRepo.newArrivalList() ,
networkRepo.getCommingSoonList()]);

// value.forEach((element) {
// print(element.toString());
// element.forEach((subelement) {
// print(subelement.toString());
// });
// });
// print(DateTime.now().toString());
final List trendingList = await networkRepo.trendingList();
final Movie featuredBanner = await networkRepo.getFeaturedBanner();final
List newArrivals = await networkRepo.newArrivalList();
final List<CommingSoon> commingSoonList =
await networkRepo.getCommingSoonList();
// print(DateTime.now().toString());
yield HomePageLoadedState(
trendingList: trendingList,
featuredBanner: featuredBanner,
newArrivals: newArrivals,
commingSoonList: commingSoonList);
} on IOException {
yield HomePageNoInternetState();
} catch (e) {
print(e.toString());
yield HomePageErrorState();
}
}
part of 'homepage_bloc.dart';

abstract class HomePageEvent extends Equatable {const


HomePageEvent();
@override
List<Object> get props => [];
}
class GetHomePageData extends HomePageEvent {const
GetHomePageData();

@override
List<Object> get props => [];
}
part of 'homepage_bloc.dart';

76
abstract class HomePageState extends Equatable {const
HomePageState();

@override
List<Object> get props => [];
}

class HomePageLoadingState extends HomePageState {const


HomePageLoadingState();

@override
List<Object> get props => [];
}

class HomePageLoadedState extends HomePageState {final


List trendingList;
final featuredBanner;
final List newArrivals;
final List<CommingSoon> commingSoonList;
HomePageLoadedState({@required this.commingSoonList,
@required this.featuredBanner,
@required this.trendingList,
@required this.newArrivals,
});
@override
List<Object> get props => [trendingList, trendingList, newArrivals , commingSoonList];
}

class HomePageNoInternetState extends HomePageState {const


HomePageNoInternetState();

@override
List<Object> get props => [];
}

class HomePageErrorState extends HomePageState {const


HomePageErrorState();

@override
List<Object> get props => [];
}

2. movie_list_bloc

import 'dart:async';
import 'dart:io';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';

import '../../../data/movies/movies.dart';
import '../../../domain/repositories/network_repo.dart';

part 'movielistpage_event.dart';
77
class MovieListPageBloc extends Bloc<MovieListPageEvent, MovieListPageState> {
MovieListPageBloc() : super(MovieListPageLoadingState());

@override
Stream<MovieListPageState> mapEventToState(
MovieListPageEvent event,
) async* {
yield MovieListPageLoadingState();
if (event is GetMovieListBaseOnCategory) {try
{
final List<Movie> moviesList =
await NetworkRepo().getMovieCategoryList(event.categoryUrl);yield
MovieListPageLoadedState(moviesList: moviesList);
} on IOException {
yield MovieListPageNoInternetState();
} catch (e) {
yield MovieListPageErrorState();
}
}
}

part of 'movielistpage_bloc.dart';

abstract class MovieListPageEvent extends Equatable {const


MovieListPageEvent();

@override
List<Object> get props => [];
}

class GetMovieListBaseOnCategory extends MovieListPageEvent {final


String categoryUrl;
const GetMovieListBaseOnCategory({@required this.categoryUrl});

@override
List<Object> get props => [categoryUrl];
}
part of 'movielistpage_bloc.dart';

abstract class MovieListPageState extends Equatable {const


MovieListPageState();

@override
List<Object> get props => [];
}
class MovieListPageLoadingState extends MovieListPageState {const
MovieListPageLoadingState();
@override
List<Object> get props => [];
}
class MovieListPageLoadedState extends MovieListPageState {final
List<Movie> moviesList;
const MovieListPageLoadedState({@required this.moviesList});

@override

78
List<Object> get props => [moviesList];
}

class MovieListPageNoInternetState extends MovieListPageState { const


MovieListPageNoInternetState();

@override
List<Object> get props => [];
}

class MovieListPageErrorState extends MovieListPageState {const


MovieListPageErrorState();

@override
List<Object> get props => [];
}

3. series_list_bloc

import 'dart:async';
import 'dart:io';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';

import '../../../data/series/series.dart';
import '../../../domain/repositories/network_repo.dart';

part 'serieslistpage_event.dart';part
'serieslistpage_state.dart';

class SeriesListPageBloc
extends Bloc<SeriesListPageEvent, SeriesListPageState> {
SeriesListPageBloc() : super(SeriesListPageLoadingState());

@override
Stream<SeriesListPageState> mapEventToState(
SeriesListPageEvent event,
) async* {
yield SeriesListPageLoadingState();
if (event is GetSeriesListBaseOnCategory) {try
{
final List<Series> seriesList =
await NetworkRepo().getSeriesCategoryList(event.categoryUrl);
yield SeriesListPageLoadedState(seriesList: seriesList);
} on IOException {
yield SeriesListPageNoInternetState();
} catch (e) {
yield SeriesListPageErrorState();
}
}
}
}

79
const SeriesListPageEvent();

@override
List<Object> get props => [];
}

class GetSeriesListBaseOnCategory extends SeriesListPageEvent {


final String categoryUrl;

const GetSeriesListBaseOnCategory({@required this.categoryUrl});

@override
List<Object> get props => [categoryUrl];
}

part of 'serieslistpage_bloc.dart';

abstract class SeriesListPageState extends Equatable {const


SeriesListPageState();

@override
List<Object> get props => [];
}

class SeriesListPageLoadingState extends SeriesListPageState {const


SeriesListPageLoadingState();
@override
List<Object> get props => [];
}

class SeriesListPageLoadedState extends SeriesListPageState {


final List<Series> seriesList;
const SeriesListPageLoadedState({@required this.seriesList});
@override
List<Object> get props => [seriesList];
}
class SeriesListPageNoInternetState extends SeriesListPageState {
const SeriesListPageNoInternetState();

@override
List<Object> get props => [];
}
class SeriesListPageErrorState extends SeriesListPageState {
const SeriesListPageErrorState();
@override
List<Object> get props => [];
}

4. channel_page_bloc
import 'dart:async';
import 'dart:io';

80
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';

import '../../../data/channels/channel.dart';
import '../../../domain/repositories/network_repo.dart';

part 'channelpage_event.dart';
part 'channelpage_state.dart';

class ChannelPageBloc extends Bloc<ChannelPageEvent, ChannelPageState> {


ChannelPageBloc() : super(ChannelPageLoadingState());

@override
Stream<ChannelPageState> mapEventToState(
ChannelPageEvent event,
) async* {
if (event is GetChannelListData) {
yield ChannelPageLoadingState();try
{
final List<Channel> channelList =
await NetworkRepo().indianChannelList();
yield ChannelPageLoadedState(channelList: channelList);
} on IOException {
yield ChannelPageNoInternetState();
} catch (e) {
print(e.toString());
yield ChannelPageErrorState();
}
}
}
}

part of 'channelpage_bloc.dart';

abstract class ChannelPageEvent extends Equatable {const


ChannelPageEvent();

@override
List<Object> get props => [];
}

class GetChannelListData extends ChannelPageEvent {const


GetChannelListData();

@override
List<Object> get props => [];
}

part of 'channelpage_bloc.dart';

abstract class ChannelPageState extends Equatable {const


ChannelPageState();

@override
List<Object> get props => [];
}

81
@override
List<Object> get props => [];
}

class ChannelPageLoadedState extends ChannelPageState {final


List<Channel> channelList;
const ChannelPageLoadedState({@required this.channelList});

@override
List<Object> get props => [channelList];
}

class ChannelPageNoInternetState extends ChannelPageState {const


ChannelPageNoInternetState();

@override
List<Object> get props => [];
}

class ChannelPageErrorState extends ChannelPageState {const


ChannelPageErrorState();

@override
List<Object> get props => [];
}

82
CHAPTER 5
DIRECTORY STRUCTURE

5.1 D structure

83
5.2 Front-End Directory Structure:

84
5.3 Back end directory structure

85
CHAPTER 6
TESTING AND SCREENSHOTS

6.1 Testing

Testing is the integral part of any System Development Life Cycle insufficient and interested
application tends to crash and result in loss of economic and manpower investment besides user’s
dissatisfaction and downfall of reputation.
The first step of system testing is to develop the plan that all aspect of system. Complements,
Correctness, Reliability and Maintainability.
Software is to be tested for the best quality assurance, an assurance that system meets the specification
and requirement for its intended use and performance.
System testing is the most useful practical process of executing the program with the implicit
intention of finding errors that makes the program fail.

6.2 Types of testing:

 Unit tests
A unit test tests a single function, method, or class. The goal of a unit test is to verify the correctness
of a unit of logic under a variety of conditions. External dependencies of the unit under test are generally
mocked out. Unit tests generally don’t read from or write to disk, render to screen, or receive user actions
from outside the process running the test. For more information regarding unit tests, you can view the
following recipes or run flutter test -- help in your terminal.

 Widget tests
A widget test (in other UI frameworks referred to as component test) tests a single widget. The goal
of a widget test is to verify that the widget’s UI looks and interacts as expected. Testing a widget involves
multiple classes and requires a test environment that provides the appropriate widget lifecycle context.
For example, the Widget being tested should be able to receive and respond to user actions and events,
perform
layout, and instantiate child widgets. A widget test is therefore more comprehensive than a unit test.
However, like a unit test, a widget test’s environment is replaced with an implementation much simpler
than a full-blown UI system.

 Integration tests
An integration test tests a complete app or a large part of an app. The goal of an integration test is
to verify that all the widgets and services being tested work together as expected. Furthermore, you can
use integration tests to verify your app’s performance.
86
Generally, an integration test runs on a real device or an OS emulator, such as iOS Simulator or
Android Emulator. The app under test is typically isolated from the test driver code to avoid skewing the
results.

6.3 Screenshots

87
88
89
90
91
92
93
94
95
96
7. Conclusion

This software is efficient to provide entertainment to user by her features movies list with
category , channel list, web series list and live telecast .

While streaming services are becoming more popular, users are still gearing towards free
streaming services like Hotstar, which takes away the amount of revenue artists are making.
However, streaming has proven to be beneficial for independent artists who are looking to get their
name more known. Streaming has also been proven to be more convenient for consumer as it is
faster and can be made available through any mobile device. Although streaming has caused a
decrease in revenue for the music industry, the use of pirated music/video has declined, which was
a major issue for the industry during the digital download era. Even more people are using free
options of music/video streaming over paid subscriptions, the amount of revenue streaming services
are earning is steadily increasing. Streaming is likely to be around for a while, but the music/video
industry should be prepared for the next change in technology

97
8. Reference

1. https://docs.flutter.dev/
2. https://medium.com/@subhashchandrashukla
3. https://www.amazon.in/Flutter-Complete-Reference-Create-beautiful-ebook/dp/B08KHKK8TR
4.https://www.linkedin.com/redir/redirect?url=https%3A%2F%2F2.zoppoz.workers.dev%3A443%2Fhttps%2Fsubhashdev121%2Egithub%2Eio%2Fs

ubhash%2F%23%2F&urlhash=BoTA&trk=public_profile_topcard-website

98

You might also like