carga inicial

This commit is contained in:
2021-05-04 16:12:48 -03:00
commit dbf070041b
88 changed files with 4809 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class AtualizarScreen extends StatefulWidget {
final String linkLoja;
AtualizarScreen({this.linkLoja});
@override
_AtualizarScreenState createState() => _AtualizarScreenState();
}
class _AtualizarScreenState extends State<AtualizarScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Aplicativos'),
// ),
body: Container(
padding: const EdgeInsets.all(8.0),
width: double.maxFinite,
color: Colors.white70,
child: Stack(
//fit: StackFit.loose,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.4,
child: Image.asset('assets/images/foguete.png',fit: BoxFit.contain,),
),
SizedBox(height: 25.0,),
Text('Atualização necessária',style: TextStyle(fontSize: 18.0,fontWeight: FontWeight.bold,color: Colors.grey.shade800),),
SizedBox(height: 25.0,),
Text('A versão atual deste aplicativo não é mais suportada. Por favor atualize o app.',textAlign: TextAlign.center,style: TextStyle(fontWeight: FontWeight.w300,color: Colors.grey.shade800)),
Expanded(
child: SafeArea(
bottom: true,
minimum: const EdgeInsets.only(bottom: 30.0),
child: Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.end,
children: [
MaterialButton(
color: Theme.of(context).primaryColor,
minWidth: MediaQuery.of(context).size.width * 0.6,
child: Text('ATUALIZAR AGORA'),
textColor: Colors.white,
//minWidth: MediaQuery.of(context).size.width * 0.5,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)
),
onPressed: (){
launch(widget.linkLoja);
}
),
],
),
),
)
],
),
],
)
),
);
}
}
+97
View File
@@ -0,0 +1,97 @@
class DefaultResponseApi {
int errorCode;
String errorMessage;
DefaultResponseApi({this.errorCode, this.errorMessage});
DefaultResponseApi.fromJson(Map<String, dynamic> json) {
errorCode = json['ErrorCode'];
errorMessage = json['ErrorMessage'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ErrorCode'] = this.errorCode;
data['ErrorMessage'] = this.errorMessage;
return data;
}
}
class RegistraDeviceRequest {
int aPPMOBILECODIGO;
int pLATAFORMAMOBILECODIGO;
String dEVICETOKEN;
String mODELODEVICE;
int uSUCOD;
RegistraDeviceRequest(
{this.aPPMOBILECODIGO,
this.pLATAFORMAMOBILECODIGO,
this.dEVICETOKEN,
this.mODELODEVICE,
this.uSUCOD});
RegistraDeviceRequest.fromJson(Map<String, dynamic> json) {
aPPMOBILECODIGO = json['APP_MOBILE_CODIGO'];
pLATAFORMAMOBILECODIGO = json['PLATAFORMA_MOBILE_CODIGO'];
dEVICETOKEN = json['DEVICE_TOKEN'];
mODELODEVICE = json['MODELO_DEVICE'];
uSUCOD = json['USU_COD'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['APP_MOBILE_CODIGO'] = this.aPPMOBILECODIGO;
data['PLATAFORMA_MOBILE_CODIGO'] = this.pLATAFORMAMOBILECODIGO;
data['DEVICE_TOKEN'] = this.dEVICETOKEN;
data['MODELO_DEVICE'] = this.mODELODEVICE;
data['USU_COD'] = this.uSUCOD;
return data;
}
}
class ApiStatusResponse {
String sistema;
String upload;
String download;
String pagamento;
int errorCode;
String errorMessage;
ApiStatusResponse(
{this.sistema,
this.upload,
this.download,
this.pagamento,
this.errorCode,
this.errorMessage});
ApiStatusResponse.fromJson(Map<String, dynamic> json) {
sistema = json['Sistema'];
upload = json['Upload'];
download = json['Download'];
pagamento = json['Pagamento'];
errorCode = json['ErrorCode'];
errorMessage = json['ErrorMessage'];
}
}
class VersaoMinimaResponse {
int versaoMinima;
String linkLoja;
String nome;
int errorCode;
String errorMessage;
bool vOk;
VersaoMinimaResponse({this.errorCode, this.errorMessage,this.linkLoja,this.nome,this.versaoMinima,this.vOk});
VersaoMinimaResponse.fromJson(Map<String, dynamic> json) {
errorCode = json['ErrorCode'];
errorMessage = json['ErrorMessage'];
versaoMinima = json['VersaoMinima'];
linkLoja = json['LinkLoja'];
nome = json['Nome'];
vOk = true;
}
}
+147
View File
@@ -0,0 +1,147 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:device_info/device_info.dart';
import 'dart:io';
import 'default_response_api.dart';
class FuncoesGerais{
//static const String urlLexLiteApi = "https://apis.lexstation.com/api/v1/";
static const String tokenPadrao = "XW3Y21GZWD9HIB8XOME4UE2APLPG3J";
static const String urlBaseNewCore = "https://newcore.services/newcore/";
static const int appMobileCodigo = 18;
static const String nomeApp = "App Cards Starter";
static const int versaoAtual = 100;
static const String youtubeApiKey = "AIzaSyAmqjP0MxgASbt98Px1_hqaIvcsqeHO15k";//"AIzaSyA8jo3qsr-JJRm40iSHfkrzaMZXdMjo9v4";
static const String channelId = "UCJ_EUoswNTvRGotJ-ROxaKw";
static const String homeURL = "https://www.decpisos.com.br/";
static const String dominioPermitido = "https://www.decpisos.com.br";
static Future<bool> checkInternetConnection() async{
bool retorno = true;
try {
final result = await InternetAddress.lookup('google.com').timeout(Duration(seconds: 5));
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
retorno = true;
}
else{
retorno = false;
}
} on SocketException catch (_) {
retorno = false;
}
catch(err){
retorno = false;
}
return retorno;
}
static Future<String> getUsuToken()async{
return Future<String>.value(tokenPadrao);
}
static Future<void> registraDevice(String token) async{
if(await FuncoesGerais.checkInternetConnection()){
if(token != null && token.isNotEmpty){
String url = FuncoesGerais.urlBaseNewCore+ "api/v1/user/${FuncoesGerais.tokenPadrao}/registra_device";
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
heads["auth-key"] = token;
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
String model = "";
int platformCoddigo = 0;
if (Platform.isAndroid) {
platformCoddigo = 2;
var info = await deviceInfo.androidInfo;
model = info.model;
} else if (Platform.isIOS) {
platformCoddigo = 1;
var info = await deviceInfo.iosInfo;
model = info.utsname.machine;
}
var objPost = new RegistraDeviceRequest(
aPPMOBILECODIGO: appMobileCodigo,
dEVICETOKEN: token,
mODELODEVICE: model,
pLATAFORMAMOBILECODIGO: platformCoddigo,
uSUCOD: 0,
);
try {
var body = json.encode(objPost);
//var response = await http.post(url, body: body,headers: heads);
var r = await http.post(url, body: body,headers: heads);
print(r);
// if (response != null) {
// if (response.statusCode == 200) {
// var data = jsonDecode(response.body);
// retorno = LoginResponse.fromJson(data);
// }
// }
} catch (e) {
}
}
}
else{
print('Nada');
}
}
static Future<VersaoMinimaResponse> checkVersaoMinimaOk() async{
VersaoMinimaResponse objRetorno = VersaoMinimaResponse(
errorCode: 0,
errorMessage: '',
linkLoja: '',
nome: '',
versaoMinima: 0,
vOk: true
);
if(await FuncoesGerais.checkInternetConnection()){
String url = FuncoesGerais.urlBaseNewCore + "api/v1/appmobile/${FuncoesGerais.tokenPadrao}/versaominima/$appMobileCodigo";
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
try {
var response = await http.get(url,headers: heads);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
objRetorno = VersaoMinimaResponse.fromJson(data);
// PackageInfo packageInfo = await PackageInfo.fromPlatform();
// var v = packageInfo.version.split('.');
// int versaoAtual = 0;
//if(v.length > 0)versaoAtual = v[0] != null && v[0].isNotEmpty ? int.parse(v[0]) : 0;
if(FuncoesGerais.versaoAtual != null && objRetorno.versaoMinima > FuncoesGerais.versaoAtual){
objRetorno.vOk = false;
}
}
else{
objRetorno.errorCode = 4;
objRetorno.errorMessage = 'Falha na comunição com a API error:${response.statusCode}.';
}
}
else{
objRetorno.errorCode = 3;
objRetorno.errorMessage = 'Falha na comunição com o server.';
}
} catch (e) {
objRetorno.errorCode = 2;
objRetorno.errorMessage = 'Falha na comunição com o server.';
}
}
else{
objRetorno.errorCode = 1;
objRetorno.errorMessage = 'Sem Conexão com a internet.';
}
return objRetorno;
}
}
+60
View File
@@ -0,0 +1,60 @@
import 'package:appcardsstarter/funcoes_gerais.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with AutomaticKeepAliveClientMixin<HomeScreen> {
bool error = false;
String msg = '';
@override
Widget build(BuildContext context) {
super.build(context);
return SafeArea(
child: this.error ? this._buildError() : WebView(
initialUrl: FuncoesGerais.homeURL,
javascriptMode: JavascriptMode.unrestricted,
onWebResourceError: (err){
this.error = true;
this.msg = err.description;
setState(() {
});
},
navigationDelegate: (navigation){
print(navigation.url);
if (navigation.url.startsWith(FuncoesGerais.dominioPermitido)) {
return NavigationDecision.navigate;
}
//print('allowing navigation to $request');
launch(navigation.url);
return NavigationDecision.prevent;
},
),
);
}
Widget _buildError(){
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(msg),
RaisedButton(onPressed: (){
this.error = false;
this.msg = '';
setState(() {
});
}, child: Text('Atualizar'),)
],
),
);
}
@override
bool get wantKeepAlive => true;
}
+55
View File
@@ -0,0 +1,55 @@
import 'package:appcardsstarter/home/home.dart';
import 'package:appcardsstarter/notificacoes/notificacoes.dart';
import 'package:appcardsstarter/videos/youtube_videos.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'package:flutter/material.dart';
class IndexScreen extends StatefulWidget {
@override
_IndexScreenState createState() => _IndexScreenState();
}
class _IndexScreenState extends State<IndexScreen> with SingleTickerProviderStateMixin{
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
_tabController.index = 1;
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: TabBarView(
controller: _tabController,
physics: NeverScrollableScrollPhysics(),
children: [
YouTubeVideosScreen(),
HomeScreen(),
NotificacoesScreen()
]
),
bottomNavigationBar: ConvexAppBar(
items: [
TabItem(icon: Icons.video_collection, title: 'Vídeos'),
TabItem(icon: Icons.home, title: 'Home'),
TabItem(icon: Icons.notifications, title: 'Notificações'),
],
style: TabStyle.flip,
backgroundColor: Theme.of(context).primaryColor,
controller: _tabController,
// onTap: (int i){
// print(i);
// },
),
);
}
}
+27
View File
@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'splash/splash.dart';
void main() {
runApp(GetMaterialApp(
title: 'LEX Station Lite',
localizationsDelegates: [
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate
],
supportedLocales: [
const Locale('pt'),
],
themeMode: ThemeMode.dark,
theme: ThemeData(
brightness: Brightness.dark,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreen()
));
}
+159
View File
@@ -0,0 +1,159 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../default_response_api.dart';
import '../../funcoes_gerais.dart';
import 'notificacoes_classes.dart';
class NotificacoesApi{
Future<NotificacoesResponse> getNotificacoes(int pagina,{String lidas = 'T',String curtidas = 'T'}) async{
var retorno = new NotificacoesResponse(
errorCode: 0,
errorMessage: "",
loadMore: false,
results: []
);
if(await FuncoesGerais.checkInternetConnection() == false){
retorno.errorCode = 1;
retorno.errorMessage = "Sem conexão com a Internet";
}
else{
var token = await FuncoesGerais.getUsuToken();
String url = FuncoesGerais.urlBaseNewCore+'api/v1/user/notificacoes/$token/$pagina/10/$lidas/$curtidas';
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
var response = await http.get(url, headers: heads);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
retorno = NotificacoesResponse.fromJson(data);
}
else{
retorno.errorCode = response.statusCode;
retorno.errorMessage = "Falha: ${response.statusCode}";
}
}
else{
retorno.errorCode = 2;
retorno.errorMessage = "Falha na comunicação com o server. Tente novamente";
}
}
return retorno;
}
Future<NotificacaoResponse> getNotificacao(int id) async{
var retorno = new NotificacaoResponse(
errorCode: 0,
errorMessage: ""
);
if(await FuncoesGerais.checkInternetConnection() == false){
retorno.errorCode = 1;
retorno.errorMessage = "Sem conexão com a Internet";
}
else{
var token = await FuncoesGerais.getUsuToken();
String url = FuncoesGerais.urlBaseNewCore+'api/v1/user/notificacao/$token/$id';
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
var response = await http.get(url, headers: heads);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
retorno = NotificacaoResponse.fromJson(data);
}
else{
retorno.errorCode = response.statusCode;
retorno.errorMessage = "Falha: ${response.statusCode}";
}
}
else{
retorno.errorCode = 2;
retorno.errorMessage = "Falha na comunicação com o server. Tente novamente";
}
}
return retorno;
}
Future<DefaultResponseApi> notificacaoLike(NotificacaoLikeRequest post) async{
DefaultResponseApi objRetorno = new DefaultResponseApi();
if(await FuncoesGerais.checkInternetConnection() == false){
objRetorno.errorCode = 1;
objRetorno.errorMessage = "Sem Conexão com a Internet.";
return objRetorno;
}
var token = await FuncoesGerais.getUsuToken();
String url = FuncoesGerais.urlBaseNewCore+'api/v1/user/notificacaolike/$token';
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
var body = json.encode(post);
var response = await http.post(url, headers: heads, body: body);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
objRetorno = DefaultResponseApi.fromJson(data);
}
else{
objRetorno.errorCode = response.statusCode;
objRetorno.errorMessage = "Falha: ${response.statusCode}";
}
}
else{
objRetorno.errorCode = 2;
objRetorno.errorMessage = "Falha na comunicação com o server. Tente novamente";
}
return objRetorno;
}
Future<DefaultResponseApi> notificacaoLida(NotificacaoLidaRequest post, int notificacaoId) async{
DefaultResponseApi objRetorno = new DefaultResponseApi();
if(await FuncoesGerais.checkInternetConnection() == false){
objRetorno.errorCode = 1;
objRetorno.errorMessage = "Sem Conexão com a Internet.";
return objRetorno;
}
var token = await FuncoesGerais.getUsuToken();
String url = FuncoesGerais.urlBaseNewCore+'api/v1/user/notificacaolida/$token/$notificacaoId';
Map<String, String> heads = Map();
heads["Content-type"] = "application/json; charset=utf-8";
var body = json.encode(post);
var response = await http.post(url, headers: heads, body: body);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
objRetorno = DefaultResponseApi.fromJson(data);
}
else{
objRetorno.errorCode = response.statusCode;
objRetorno.errorMessage = "Falha: ${response.statusCode}";
}
}
else{
objRetorno.errorCode = 2;
objRetorno.errorMessage = "Falha na comunicação com o server. Tente novamente";
}
return objRetorno;
}
}
@@ -0,0 +1,142 @@
class NotificacaoLikeRequest {
int iD;
String like;
NotificacaoLikeRequest({this.iD, this.like});
NotificacaoLikeRequest.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
like = json['Like'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['Like'] = this.like;
return data;
}
}
class NotificacaoLidaRequest {
String latitude;
String longitude;
NotificacaoLidaRequest({this.latitude, this.longitude});
NotificacaoLidaRequest.fromJson(Map<String, dynamic> json) {
latitude = json['Latitude'];
longitude = json['Longitude'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Latitude'] = this.latitude;
data['Longitude'] = this.longitude;
return data;
}
}
class NotificacaoResponse {
NotificacaoResults result;
int errorCode;
String errorMessage;
NotificacaoResponse({this.result, this.errorCode, this.errorMessage});
NotificacaoResponse.fromJson(Map<String, dynamic> json) {
result =
json['Result'] != null ? new NotificacaoResults.fromJson(json['Result']) : null;
errorCode = json['ErrorCode'];
errorMessage = json['ErrorMessage'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.result != null) {
data['Result'] = this.result.toJson();
}
data['ErrorCode'] = this.errorCode;
data['ErrorMessage'] = this.errorMessage;
return data;
}
}
class NotificacoesResponse {
List<NotificacaoResults> results;
int errorCode;
String errorMessage;
bool loadMore;
NotificacoesResponse({this.results, this.errorCode, this.errorMessage,this.loadMore});
NotificacoesResponse.fromJson(Map<String, dynamic> json) {
if (json['Results'] != null) {
results = new List<NotificacaoResults>();
json['Results'].forEach((v) {
results.add(new NotificacaoResults.fromJson(v));
});
}
errorCode = json['ErrorCode'];
errorMessage = json['ErrorMessage'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.results != null) {
data['Results'] = this.results.map((v) => v.toJson()).toList();
}
data['ErrorCode'] = this.errorCode;
data['ErrorMessage'] = this.errorMessage;
return data;
}
}
class NotificacaoResults {
int iD;
String titulo;
String texto;
String conteudo;
String dataNotificacao;
String tipoConteudo;
bool visualizado;
String imageUrl;
String like;
NotificacaoResults(
{this.iD,
this.titulo,
this.texto,
this.conteudo,
this.dataNotificacao,
this.tipoConteudo,
this.visualizado,
this.imageUrl,
this.like = ''});
NotificacaoResults.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
titulo = json['Titulo'] ?? '';
texto = json['Texto'];
conteudo = json['Conteudo'];
dataNotificacao = json['DataNotificacao'];
tipoConteudo = json['TipoConteudo'];
visualizado = json['Visualizado'];
imageUrl = json['ImageUrl'];
like = json['Like'] ?? '';
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['Titulo'] = this.titulo;
data['Texto'] = this.texto;
data['Conteudo'] = this.conteudo;
data['DataNotificacao'] = this.dataNotificacao;
data['TipoConteudo'] = this.tipoConteudo;
data['Visualizado'] = this.visualizado;
data['ImageUrl'] = this.imageUrl;
data['Like'] = this.like;
return data;
}
}
+63
View File
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';
import 'notificacoes_controller.dart';
class NotificacaoDetail extends StatelessWidget {
final NotificacoesController c = Get.find();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//
//title: Obx(() => Text(c.notificacaoDetail.value.result.titulo ?? 'Notificação')),
),
body: Obx(() => c.loadingDetail.value ? Center(child: CircularProgressIndicator(),) : c.notificacaoDetail.value.errorCode != 0 ? Center(child: Text(c.notificacaoDetail.value.errorMessage),) : ListView(
children: <Widget>[
Visibility(
visible: GetUtils.isNullOrBlank(c.notificacaoDetail.value.result.imageUrl) == false,
child: Container(
color: Colors.black38,
height: 250,
child: Padding(
padding: const EdgeInsets.all(70.0),
child: Image.network(
c.notificacaoDetail.value.result.imageUrl ?? '',
fit: BoxFit.contain,
),
),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
c.notificacaoDetail.value.result.titulo,
style: TextStyle(fontSize: 30.0,),
),
const SizedBox(height: 10),
Html(
data: c.notificacaoDetail.value.result.conteudo,
onLinkTap: (url){
launch(url);
},
// style: Theme.of(context).textTheme.bodyText2.copyWith(
// color: Colors.black54,
// height: 1.5,
// fontSize: 16.0,
// ),
),
],
),
),
],
),
),
);
}
}
+168
View File
@@ -0,0 +1,168 @@
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';
import 'notificacao.dart';
import 'notificacoes_controller.dart';
//import 'package:supercharged/supercharged.dart';
class NotificacoesScreen extends StatelessWidget {
final NotificacoesController c = Get.put(NotificacoesController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Notificações'),
centerTitle: false,
),
body: Obx(() => c.loading.value ? Center(child: CircularProgressIndicator(),) : c.errorCode.value != 0 ? this._buildError() : RefreshIndicator(
onRefresh: c.refresh,
// child: AnimatedList(
// key: c.listKey,
// padding: const EdgeInsets.all(8.0),
// initialItemCount: c.notificacoesResults.length + 1,
// itemBuilder: (context,index,animation){
// if (index < c.notificacoesResults.length) {
// return SlideTransition(
// //position: c.animation,
// position: Tween<Offset>(
// begin: const Offset(-1, 0),
// end: Offset(0, 0),
// ).animate(animation),
// child: this._buildListTile(index)
// );
// } else if (index > 1) {
// if(c.loadMore == null || c.loadMore){
// c.getNotificacoesBloc();
// return Container(
// height: 40,
// width: 40,
// alignment: Alignment.center,
// child: CircularProgressIndicator(),
// );
// }
// else{
// return Center(child: Padding(
// padding: const EdgeInsets.only(top: 8.0),
// child: Text("Não há mais Notificações para exibir."),
// ),);
// }
// }
// else {
// return Center(child: Padding(
// padding: const EdgeInsets.only(top: 8.0),
// child: Text("Não há mais Notificações para exibir."),
// ),);
// }
// }
// ),
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: c.notificacoesResults.length + 1,
itemBuilder: (_,index){
if (index < c.notificacoesResults.length) {
return this._buildListTile(index);
// return SlideTransition(
// position: c.animation,
// child: this._buildListTile(index)
// );
} else if (index > 1) {
if(c.loadMore == null || c.loadMore){
c.getNotificacoesBloc();
return Container(
height: 40,
width: 40,
alignment: Alignment.center,
child: CircularProgressIndicator(),
);
}
else{
return Center(child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text("Não há mais Notificações para exibir."),
),);
}
}
else {
return Center(child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text("Não há mais Notificações para exibir."),
),);
}
},
),
)),
// body: ListView(
// padding: const EdgeInsets.all(8.0),
// children: <Widget>[
// ...List<Widget>.generate(10, (int index) {
// return this._buildListTile(index);
// }),
// ],
// ),
);
}
Widget _buildError(){
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(c.errorMessage),
RaisedButton(onPressed: c.refresh, child: Text('Atualizar'),)
],
),
);
}
Widget _buildListTile(int index) {
if(c.notificacoesResults[index].tipoConteudo == 'L'){
return this._buildListTileTile(index: index,onTap: (){
c.notificacaoLidaBloc(c.notificacoesResults[index].iD).then((value) => launch(c.notificacoesResults[index].conteudo));
});
}
return OpenContainer<bool>(
//openColor: Colors.transparent,
closedColor: Colors.black87.withOpacity(0.2),
transitionType: ContainerTransitionType.fadeThrough,
openBuilder: (BuildContext _, VoidCallback openContainer) {
c.notificacoesResults[index].visualizado = true;
c.getNotificacaoDetail(c.notificacoesResults[index].iD);
//return _DetailsPage();
return NotificacaoDetail();
},
onClosed: (bool isMarkedAsDone) {
c.notificacaoLidaBloc(c.notificacoesResults[index].iD);
if (isMarkedAsDone ?? false)
Get.rawSnackbar(message: 'Marked as done!');
},
tappable: false,
closedShape: const RoundedRectangleBorder(),
closedElevation: 0.0,
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return this._buildListTileTile(index: index,onTap: openContainer);
},
);
}
Widget _buildListTileTile({Function onTap,@required int index}){
return ListTile(
leading: CircleAvatar(
backgroundImage: GetUtils.isNullOrBlank(c.notificacoesResults[index].imageUrl) ? AssetImage(
'assets/images/logo.png',
) : NetworkImage(c.notificacoesResults[index].imageUrl),
// child: Image.asset(
// 'assets/images/logo.png',
// width: 40,
// ),
),
onTap: onTap,
trailing: c.notificacoesResults[index].visualizado ? Text('') : Text('',style: TextStyle(color: Colors.blue),),
title: Text(c.notificacoesResults[index].titulo),
subtitle: Text(c.getDateFormatada(c.notificacoesResults[index].dataNotificacao)),
);
}
}
@@ -0,0 +1,102 @@
//import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'api/notificacoes_api.dart';
import 'api/notificacoes_classes.dart';
class NotificacoesController extends GetxController with SingleGetTickerProviderMixin{
var notificacoesResults = List<NotificacaoResults>().obs;
bool loadMore = true;
NotificacoesApi _api = new NotificacoesApi();
var notificacaoDetail = NotificacaoResponse().obs;
int page = 1;
var errorCode = 0.obs;
var errorMessage = '';
var loading = true.obs;
var loadingDetail = true.obs;
var like = ''.obs;
final f = DateFormat('dd/MM/yyyy HH:mm:ss');
//final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
// AnimationController _controller;
// Animation<Offset> animation;
@override
void onInit() {
super.onInit();
// _controller = AnimationController(
// duration: const Duration(milliseconds: 650),
// vsync: this,
// )..forward();
// animation = Tween<Offset>(
// begin: const Offset(-0.5, 0.0),
// end: const Offset(0.0, 0.0),
// ).animate(CurvedAnimation(
// parent: _controller,
// curve: Curves.easeInCubic,
// ));
this.notificacoesResults = new RxList<NotificacaoResults>();
this.getNotificacoesBloc();
}
getNotificacoesBloc()async{
var response = await this._api.getNotificacoes(page);
this.loadMore = response.results.length < 1 ? false : true;
if(response.errorCode != 0){
this.errorCode.value = response.errorCode;
this.errorMessage = response.errorMessage;
}
else{
//if(this.page > 1)this.listKey.currentState.insertItem(2,duration: const Duration(milliseconds: 1500));
page++;
this.notificacoesResults.addAll(response.results);
}
if(this.loading.value)this.loading.value = false;
}
getNotificacaoDetail(int id) async {
this.loadingDetail.value = true;
this.notificacaoDetail.value.result = new NotificacaoResults();
var response = await this._api.getNotificacao(id);
this.notificacaoDetail.value = response;
this.like.value = response.result.like;
this.loadingDetail.value = false;
}
Future<void> refresh() async{
this.loading.value = true;
this.page = 1;
this.notificacoesResults = new RxList<NotificacaoResults>();
this.getNotificacoesBloc();
}
String get getLike => this.like.value;
Future<void> notificacaoLikeBloc(NotificacaoLikeRequest item) async {
var response = await this._api.notificacaoLike(item);
if(response != null && response.errorCode == 0)
{
this.notificacaoDetail.value.result.like = item.like;
this.like.value = item.like;
}
}
String getDateFormatada(String dt){
String r = '';
try {
r = this.f.format(DateTime.parse(dt));
} catch (e) {
}
return r;
}
Future<void> notificacaoLidaBloc(int notificacaoID) async {
return;
}
}
+45
View File
@@ -0,0 +1,45 @@
import 'package:appcardsstarter/funcoes_gerais.dart';
import 'package:flutter/material.dart';
import 'package:animated_splash_screen/animated_splash_screen.dart';
import 'package:get/get.dart';
import 'package:page_transition/page_transition.dart';
import 'splash_controller.dart';
class SplashScreen extends StatelessWidget {
final SplashController c = Get.put(SplashController());
@override
Widget build(BuildContext context) {
return AnimatedSplashScreen.withScreenFunction(
splash: Container(
width: double.maxFinite,
height: Get.size.height,
//color: Colors.red,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Container(width: 120.0,height: 120.0,child: Image.asset('assets/images/logo.png',fit: BoxFit.contain,))
),
SizedBox(height: 10.0,),
Text(FuncoesGerais.nomeApp,style: TextStyle(color: Colors.green.shade600,fontSize: 22.0),),
LinearProgressIndicator()
],
),
),
//splashIconSize: 90.0,
splashIconSize: Get.size.height,
splashTransition: SplashTransition.slideTransition,
pageTransitionType: PageTransitionType.fade,
backgroundColor: Colors.white,
screenFunction: ()async{
await c.firebaseCloudMessagingListeners();
await c.verTutorial();
var screen = await c.verUsuLogado();
return screen;
},
//backgroundColor: Colors.blue
);
}
}
+89
View File
@@ -0,0 +1,89 @@
import 'dart:io';
import 'package:appcardsstarter/atualizarapp/atualizarapp.dart';
import 'package:appcardsstarter/index/index.dart';
import 'package:appcardsstarter/notificacoes/notificacoes.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../funcoes_gerais.dart';
class SplashController extends GetxController {
bool _tutorialOk = false;
FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
@override
void onInit() {
super.onInit();
}
@override
void onClose() {
super.onClose();
}
Future<void> verTutorial()async{
SharedPreferences prefs = await SharedPreferences.getInstance();
this._tutorialOk = prefs.getBool('tutorial') ?? false;
}
Future<Widget> verUsuLogado()async{
var resp = await FuncoesGerais.checkVersaoMinimaOk();
if(resp.vOk){
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token_notif');
await FuncoesGerais.registraDevice(token);
return IndexScreen();
}
else{
return AtualizarScreen(linkLoja: resp.linkLoja);
}
}
Future<void> firebaseCloudMessagingListeners() async{
try {
if (_firebaseMessaging == null) return;
if (Platform.isIOS) iOSPermission();
_firebaseMessaging.getToken().then((token) async {
print(token);
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('token_notif', token);
});
_firebaseMessaging.configure(
onLaunch: this._onNotification,
onMessage: this._onNotification,
//onBackgroundMessage: this._onNotification,
onResume: this._onNotification
);
} on PlatformException catch (e) {
print(e.message);
}
}
Future<dynamic> _onNotification(Map<String, dynamic> message) async{
Get.to(() => NotificacoesScreen());
//print(message);
//print(message['aps']['alert']['title']);
//Get.rawSnackbar(message: message['aps']['alert']['title']);
}
void iOSPermission() {
_firebaseMessaging.requestNotificationPermissions(
IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
}
}
+63
View File
@@ -0,0 +1,63 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../funcoes_gerais.dart';
import 'youtube_classes.dart';
class YouTubeApi{
Future<YouTubeSearchResponse> getChannelVideos({String nextPageToken = ''}) async {
var retorno = new YouTubeSearchResponse(
errorCode: 0,
errorMessage: '',
etag: '',
items: [],
kind: '',
nextPageToken: '',
);
if (await FuncoesGerais.checkInternetConnection() == false) {
retorno.errorCode = 1;
retorno.errorMessage = "Sem conexão com a internet";
return retorno;
}
String url = "https://www.googleapis.com/youtube/v3/search?key=${FuncoesGerais.youtubeApiKey}&channelId=${FuncoesGerais.channelId}&part=snippet,id&order=date&maxResults=10";
if(nextPageToken.isNotEmpty) url += "&pageToken=$nextPageToken";
try{
var response = await http.get(url);
if (response != null) {
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
retorno = YouTubeSearchResponse.fromJson(data);
} else {
var data = jsonDecode(response.body);
retorno.errorCode = 2;
retorno.errorMessage = "Erro inesperado, tente novamente mais tarde. #${response.statusCode}";
if(data != null && data['error'] != null){
if(data['error']['message'] != null && data['error']['message'].toString().isNotEmpty){
retorno.errorMessage = data['error']['message'].toString();
}
}
return retorno;
}
} else {
retorno.errorCode = 2;
retorno.errorMessage = "Erro inesperado, tente novamente mais tarde";
return retorno;
}
} catch (e) {
retorno.errorCode = 2;
retorno.errorMessage = "Falha interna no App, tente novamenre mais tarde.";
return retorno;
}
return retorno;
}
}
+182
View File
@@ -0,0 +1,182 @@
class YouTubeSearchResponse {
String kind;
String etag;
String nextPageToken;
String regionCode;
PageInfo pageInfo;
List<YouTubeItems> items;
int errorCode;
String errorMessage;
YouTubeSearchResponse({this.kind, this.etag, this.nextPageToken, this.regionCode, this.pageInfo, this.items,this.errorCode = 0, this.errorMessage = ''});
YouTubeSearchResponse.fromJson(Map<String, dynamic> json) {
kind = json['kind'] ?? '';
etag = json['etag'] ?? '';
nextPageToken = json['nextPageToken'] ?? '';
regionCode = json['regionCode'] ?? '';
pageInfo = json['pageInfo'] != null ? new PageInfo.fromJson(json['pageInfo']) : null;
if (json['items'] != null) {
items = new List<YouTubeItems>();
json['items'].forEach((v) { items.add(new YouTubeItems.fromJson(v)); });
}
errorCode = 0;
errorMessage = '';
}
}
class PageInfo {
int totalResults;
int resultsPerPage;
PageInfo({this.totalResults, this.resultsPerPage});
PageInfo.fromJson(Map<String, dynamic> json) {
totalResults = json['totalResults'];
resultsPerPage = json['resultsPerPage'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['totalResults'] = this.totalResults;
data['resultsPerPage'] = this.resultsPerPage;
return data;
}
}
class YouTubeItems {
String kind;
String etag;
Id id;
Snippet snippet;
YouTubeItems({this.kind, this.etag, this.id, this.snippet});
YouTubeItems.fromJson(Map<String, dynamic> json) {
kind = json['kind'];
etag = json['etag'];
id = json['id'] != null ? new Id.fromJson(json['id']) : null;
snippet = json['snippet'] != null ? new Snippet.fromJson(json['snippet']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['kind'] = this.kind;
data['etag'] = this.etag;
if (this.id != null) {
data['id'] = this.id.toJson();
}
if (this.snippet != null) {
data['snippet'] = this.snippet.toJson();
}
return data;
}
}
class Id {
String kind;
String videoId;
Id({this.kind, this.videoId});
Id.fromJson(Map<String, dynamic> json) {
kind = json['kind'];
videoId = json['videoId'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['kind'] = this.kind;
data['videoId'] = this.videoId;
return data;
}
}
class Snippet {
String publishedAt;
String channelId;
String title;
String description;
Thumbnails thumbnails;
String channelTitle;
String liveBroadcastContent;
String publishTime;
Snippet({this.publishedAt, this.channelId, this.title, this.description, this.thumbnails, this.channelTitle, this.liveBroadcastContent, this.publishTime});
Snippet.fromJson(Map<String, dynamic> json) {
publishedAt = json['publishedAt'];
channelId = json['channelId'];
title = json['title'];
description = json['description'];
thumbnails = json['thumbnails'] != null ? new Thumbnails.fromJson(json['thumbnails']) : null;
channelTitle = json['channelTitle'];
liveBroadcastContent = json['liveBroadcastContent'];
publishTime = json['publishTime'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['publishedAt'] = this.publishedAt;
data['channelId'] = this.channelId;
data['title'] = this.title;
data['description'] = this.description;
if (this.thumbnails != null) {
data['thumbnails'] = this.thumbnails.toJson();
}
data['channelTitle'] = this.channelTitle;
data['liveBroadcastContent'] = this.liveBroadcastContent;
data['publishTime'] = this.publishTime;
return data;
}
}
class Thumbnails {
ThumbDefault thumbDefault;
ThumbDefault medium;
ThumbDefault high;
Thumbnails({this.thumbDefault, this.medium, this.high});
Thumbnails.fromJson(Map<String, dynamic> json) {
thumbDefault = json['default'] != null ? new ThumbDefault.fromJson(json['default']) : null;
medium = json['medium'] != null ? new ThumbDefault.fromJson(json['medium']) : null;
high = json['high'] != null ? new ThumbDefault.fromJson(json['high']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.thumbDefault != null) {
data['default'] = this.thumbDefault.toJson();
}
if (this.medium != null) {
data['medium'] = this.medium.toJson();
}
if (this.high != null) {
data['high'] = this.high.toJson();
}
return data;
}
}
class ThumbDefault {
String url;
int width;
int height;
ThumbDefault({this.url, this.width, this.height});
ThumbDefault.fromJson(Map<String, dynamic> json) {
url = json['url'];
width = json['width'];
height = json['height'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['url'] = this.url;
data['width'] = this.width;
data['height'] = this.height;
return data;
}
}
+83
View File
@@ -0,0 +1,83 @@
import 'package:appcardsstarter/videos/api/youtube_api.dart';
import 'package:appcardsstarter/videos/api/youtube_classes.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart' show DateFormat;
class YouTubeController extends GetxController {
YouTubeApi _api = new YouTubeApi();
var results = new YouTubeSearchResponse(
errorCode: 0,
errorMessage: '',
items: [],
).obs;
var itens = <YouTubeItems>[].obs;
bool atualizar = false;
var errorCode = 0.obs;
var errorMessage = '';
var loading = true.obs;
final f = DateFormat('dd/MM/yyyy HH:mm:ss');
@override
void onInit() {
super.onInit();
// _controller = AnimationController(
// duration: const Duration(milliseconds: 650),
// vsync: this,
// )..forward();
// animation = Tween<Offset>(
// begin: const Offset(-0.5, 0.0),
// end: const Offset(0.0, 0.0),
// ).animate(CurvedAnimation(
// parent: _controller,
// curve: Curves.easeInCubic,
// ));
this.atualizar = true;
this.itens = new RxList<YouTubeItems>();
this.getChannelVideosBloc();
}
Future<void> getChannelVideosBloc({String textoBusca = '-'}) async {
//this.loading.value = true;
if (results == null || atualizar || results.value.errorCode != 0) {
results.value = new YouTubeSearchResponse();
this.itens = new RxList<YouTubeItems>();
results.value = await this._api.getChannelVideos();
results.value.items = results.value.items.where((element) => GetUtils.isNullOrBlank(element.id.videoId) == false).toList();
this.itens.addAll(results.value.items);
this.errorCode.value = results.value.errorCode;
this.errorMessage = results.value.errorMessage;
this.atualizar = false;
} else if (results.value.nextPageToken != null && results.value.nextPageToken.isNotEmpty) {
var more = await this._api.getChannelVideos(nextPageToken: results.value.nextPageToken);
more.items = more.items.where((element) => GetUtils.isNullOrBlank(element.id.videoId) == false).toList();
this.errorCode.value = more.errorCode;
this.errorMessage = more.errorMessage;
this.itens.addAll(more.items);
results.value.nextPageToken = more.nextPageToken ?? '';
results.value.items += more.items;
}
this.loading.value = false;
}
Future<void> refresh() async {
this.loading.value = true;
this.atualizar = true;
results.value = YouTubeSearchResponse(
errorCode: 0,
errorMessage: '',
items: [],
);
this.getChannelVideosBloc();
}
String getDateFormatada(String dt){
String r = '';
try {
r = this.f.format(DateTime.parse(dt));
} catch (e) {
}
return r;
}
}
+273
View File
@@ -0,0 +1,273 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_youtube_view/flutter_youtube_view.dart';
// class YoutubeCustomWidget extends StatefulWidget {
// @override
// _MyAppState createState() => _MyAppState();
// }
// class _MyAppState extends State<YoutubeCustomWidget>
// implements YouTubePlayerListener {
// double _volume = 50;
// double _videoDuration = 0.0;
// double _currentVideoSecond = 0.0;
// String _playerState = "";
// FlutterYoutubeViewController _controller;
// YoutubeScaleMode _mode = YoutubeScaleMode.none;
// PlaybackRate _playbackRate = PlaybackRate.RATE_1;
// bool _isMuted = false;
// @override
// void onCurrentSecond(double second) {
// // print("onCurrentSecond second = $second");
// _currentVideoSecond = second;
// }
// @override
// void onError(String error) {
// print("onError error = $error");
// }
// @override
// void onReady() {
// print("onReady");
// }
// @override
// void onStateChange(String state) {
// print("onStateChange state = $state");
// setState(() {
// _playerState = state;
// });
// }
// @override
// void onVideoDuration(double duration) {
// print("onVideoDuration duration = $duration");
// }
// void _onYoutubeCreated(FlutterYoutubeViewController controller) {
// this._controller = controller;
// }
// void _loadOrCueVideo() {
// _controller.loadOrCueVideo('gcj2RUWQZ60', _currentVideoSecond);
// }
// void _play() {
// _controller.play();
// }
// void _pause() {
// _controller.pause();
// }
// void _seekTo(double time) {
// _controller.seekTo(time);
// }
// void _setVolume(int volumePercent) {
// _controller.setVolume(volumePercent);
// }
// void _changeScaleMode(YoutubeScaleMode mode) {
// setState(() {
// _mode = mode;
// _controller.changeScaleMode(mode);
// });
// }
// void _changeVolumeMode(bool isMuted) {
// setState(() {
// _isMuted = isMuted;
// if (isMuted) {
// _controller.setMute();
// } else {
// _controller.setUnMute();
// }
// });
// }
// void _changePlaybackRate(PlaybackRate playbackRate) {
// setState(() {
// _playbackRate = playbackRate;
// _controller.setPlaybackRate(playbackRate);
// });
// }
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: const Text('Custom UI')
// ),
// body: Stack(
// children: <Widget>[
// Container(
// child: FlutterYoutubeView(
// scaleMode: _mode,
// onViewCreated: _onYoutubeCreated,
// listener: this,
// params: YoutubeParam(
// videoId: 'gcj2RUWQZ60',
// showUI: false,
// startSeconds: 0.0,
// autoPlay: false,
// ),
// )),
// Column(
// children: <Widget>[
// Text(
// 'Current state: $_playerState',
// style: TextStyle(color: Colors.blue),
// ),
// RaisedButton(
// onPressed: _loadOrCueVideo,
// child: Text('Click reload video'),
// ),
// _buildControl(),
// _buildVolume(),
// _buildScaleModeRadioGroup(),
// _buildPlaybackRate()
// ],
// )
// ],
// ));
// }
// Widget _buildControl() {
// return new Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// children: <Widget>[
// RaisedButton(
// onPressed: _play,
// child: Text('Play'),
// ),
// RaisedButton(
// onPressed: _pause,
// child: Text('Pause'),
// ),
// RaisedButton(
// onPressed: () {
// _seekTo(20.0);
// },
// child: Text('seekTo 20s'),
// )
// ],
// );
// }
// Widget _buildScaleModeRadioGroup() {
// return new Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// new Radio(
// value: YoutubeScaleMode.none,
// groupValue: _mode,
// onChanged: _changeScaleMode,
// ),
// new Text(
// 'none',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: YoutubeScaleMode.fitWidth,
// groupValue: _mode,
// onChanged: _changeScaleMode,
// ),
// new Text(
// 'fitWidth',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: YoutubeScaleMode.fitHeight,
// groupValue: _mode,
// onChanged: _changeScaleMode,
// ),
// new Text(
// 'fitHeight',
// style: TextStyle(color: Colors.blue),
// ),
// ],
// );
// }
// Widget _buildVolume() {
// return new Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// new Radio(
// value: false,
// groupValue: _isMuted,
// onChanged: _changeVolumeMode,
// ),
// new Text(
// 'unMute',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: true,
// groupValue: _isMuted,
// onChanged: _changeVolumeMode,
// ),
// new Text(
// 'Mute',
// style: TextStyle(color: Colors.blue),
// )
// ],
// );
// }
// Widget _buildPlaybackRate() {
// return new Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// new Radio(
// value: PlaybackRate.RATE_0_25,
// groupValue: _playbackRate,
// onChanged: _changePlaybackRate,
// ),
// new Text(
// '0_25',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: PlaybackRate.RATE_0_5,
// groupValue: _playbackRate,
// onChanged: _changePlaybackRate,
// ),
// new Text(
// '0_5',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: PlaybackRate.RATE_1,
// groupValue: _playbackRate,
// onChanged: _changePlaybackRate,
// ),
// new Text(
// '1',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: PlaybackRate.RATE_1_5,
// groupValue: _playbackRate,
// onChanged: _changePlaybackRate,
// ),
// new Text(
// '1_5',
// style: TextStyle(color: Colors.blue),
// ),
// new Radio(
// value: PlaybackRate.RATE_2,
// groupValue: _playbackRate,
// onChanged: _changePlaybackRate,
// ),
// new Text(
// '2',
// style: TextStyle(color: Colors.blue),
// )
// ],
// );
// }
// }
@@ -0,0 +1,90 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_youtube_view/flutter_youtube_view.dart';
// class YoutubeDefaultWidget extends StatefulWidget {
// final String id;
// YoutubeDefaultWidget({this.id});
// @override
// _MyAppState createState() => _MyAppState();
// }
// class _MyAppState extends State<YoutubeDefaultWidget>
// implements YouTubePlayerListener {
// //double _currentVideoSecond = 0.0;
// //String _playerState = "";
// //FlutterYoutubeViewController _controller;
// @override
// void onCurrentSecond(double second) {
// // print("onCurrentSecond second = $second");
// // _currentVideoSecond = second;
// }
// @override
// void onError(String error) {
// print("onError error = $error");
// }
// @override
// void onReady() {
// print("onReady");
// }
// @override
// void onStateChange(String state) {
// // print("onStateChange state = $state");
// // setState(() {
// // _playerState = state;
// // });
// }
// @override
// void onVideoDuration(double duration) {
// print("onVideoDuration duration = $duration");
// }
// void _onYoutubeCreated(FlutterYoutubeViewController controller) {
// //this._controller = controller;
// }
// // void _loadOrCueVideo() {
// // _controller.loadOrCueVideo('gcj2RUWQZ60', _currentVideoSecond);
// // }
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(),
// body: Stack(
// children: <Widget>[
// AspectRatio(
// aspectRatio: 16/9,
// child: FlutterYoutubeView(
// onViewCreated: _onYoutubeCreated,
// listener: this,
// params: YoutubeParam(
// videoId: widget.id,
// showUI: true,
// //startSeconds: 5 * 60.0,
// autoPlay: true,
// showYoutube: false,
// showFullScreen: true,
// ),
// )),
// // Center(
// // child: Column(
// // children: <Widget>[
// // Text(
// // 'Current state: $_playerState',
// // style: TextStyle(color: Colors.blue),
// // ),
// // RaisedButton(
// // onPressed: _loadOrCueVideo,
// // child: Text('Click reload video'),
// // ),
// // ],
// // ))
// ],
// ));
// }
// }
+76
View File
@@ -0,0 +1,76 @@
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'api/youtube_classes.dart';
class YouTubeVideoPlayerScreen extends StatefulWidget {
final YouTubeItems ytVideo;
YouTubeVideoPlayerScreen({@required this.ytVideo});
@override
_YouTubeVideoPlayerScreenState createState() => _YouTubeVideoPlayerScreenState();
}
class _YouTubeVideoPlayerScreenState extends State<YouTubeVideoPlayerScreen> {
YoutubePlayerController _controller;
bool _fullScreen = false;
@override
void initState() {
super.initState();
_controller = new YoutubePlayerController(initialVideoId: widget.ytVideo.id.videoId);
}
@override
void dispose() {
//_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
//appBar: AppBar(),
body: SafeArea(
child: YoutubePlayerBuilder(
player: YoutubePlayer(
controller: _controller,
topActions: [
IconButton(icon: Icon(Icons.close),onPressed: (){
if(this._fullScreen){
_controller.toggleFullScreenMode();
}
else{
Navigator.of(context).pop();
}
}),
],
),
onEnterFullScreen: (){
this._fullScreen = true;
},
onExitFullScreen: ()=>this._fullScreen = false,
builder: (context,player){
return Column(
children: [
player,
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(widget.ytVideo.snippet.title),
SizedBox(height: 10.0,),
Text(widget.ytVideo.snippet.description),
],
),
)
),
],
);
},
),
)
);
}
}
+324
View File
@@ -0,0 +1,324 @@
import 'package:appcardsstarter/videos/youtube_video_player.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:get/get.dart';
import 'package:transparent_image/transparent_image.dart';
//import 'players/YoutubeCustomWidget.dart';
import 'api/youtube_classes.dart';
import 'bloc/youtube_controller.dart';
//import 'players/YoutubeDefaultWidget.dart';
// class YouTubeVideosScreen extends StatelessWidget {
// final YouTubeController c = Get.put(YouTubeController());
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: Text('Vídeos'),
// ),
// body: Obx(() => c.loading.value ? Center(child: CircularProgressIndicator(),) : c.errorCode.value != 0 ? this._buildError() : RefreshIndicator(
// onRefresh: c.refresh,
// child: AnimationLimiter(
// child: ListView.builder(
// padding: const EdgeInsets.all(8.0),
// itemCount: c.itens.length + 1,
// itemBuilder: (_,index){
// if (index < c.itens.length) {
// var item = c.itens[index];
// return AnimationConfiguration.staggeredList(
// position: index,
// duration: const Duration(milliseconds: 375),
// child: SlideAnimation(
// verticalOffset: 30.0,
// child: FadeInAnimation(
// child: listItem(item),
// )
// )
// );
// // return SlideTransition(
// // position: c.animation,
// // child: this._buildListTile(index)
// // );
// } else if (index > 1) {
// if (!GetUtils.isNullOrBlank(c.results.value.nextPageToken)) {
// c.getChannelVideosBloc();
// return Center(child: CircularProgressIndicator(),);
// } else {
// return Center(
// child: Padding(
// padding: const EdgeInsets.only(top: 8.0,bottom: 25.0),
// child:
// Text("Não há mais Vídeos para exibir."),
// ),
// );
// }
// }
// else {
// return Center(child: Padding(
// padding: const EdgeInsets.only(top: 8.0),
// child: Text("Não há mais Vídeos para exibir."),
// ),);
// }
// },
// ),
// ),
// )),
// );
// }
// Widget listItem(YouTubeItems item) {
// return InkWell(
// onTap: (){
// showModalBottomSheet(context: Get.context, builder: (_)=>Container(
// child: Column(
// children: [
// ListTile(
// title: Text('Player 1'),
// onTap: (){
// Get.to(() => YouTubeVideoPlayerScreen(ytVideo: item,));
// },
// ),
// // ListTile(
// // title: Text('Player 2 - YoutubeDefaultWidget'),
// // onTap: (){
// // Navigator.of(context).push(MaterialPageRoute(builder: (_)=>YoutubeDefaultWidget(id: item.id.videoId)));
// // },
// // ),
// // ListTile(
// // title: Text('Player 3 - YoutubeCustomWidget'),
// // onTap: (){
// // Navigator.of(context).push(MaterialPageRoute(builder: (_)=>YoutubeCustomWidget()));
// // },
// // ),
// // ListTile(
// // title: Text('Player 3 - API key'),
// // onTap: (){
// // FlutterYoutube.playYoutubeVideoById(
// // apiKey:FuncoesGerais.youtubeApiKey,
// // videoId: item.id.videoId,
// // autoPlay: true, //default falase
// // fullScreen: true //default false
// // );
// // },
// // )
// ],
// ),
// ));
// },
// child: Card(
// elevation: 0,
// color: Colors.transparent,
// child: Container(
// //margin: EdgeInsets.only(bottom: 8.0),
// child: Row(
// children: <Widget>[
// LimitedBox(
// maxHeight: 100.0,
// child: AspectRatio(
// aspectRatio: 4/3,
// child: FadeInImage.memoryNetwork(
// placeholder: kTransparentImage,
// image: item.snippet?.thumbnails?.thumbDefault?.url ?? '',
// fit: BoxFit.cover,
// ),
// ),
// ),
// Padding(padding: EdgeInsets.only(right: 10.0)),
// Expanded(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: <Widget>[
// Text(
// item.snippet.title,
// softWrap: true,
// maxLines: 2,
// style: TextStyle(fontSize: 13.0,fontWeight: FontWeight.bold),
// ),
// Padding(padding: EdgeInsets.only(bottom: 1.5)),
// Text(
// item.snippet.description,
// softWrap: true,
// maxLines: 3,
// style: TextStyle(fontSize: 11.0,fontWeight: FontWeight.w400),
// ),
// Padding(padding: EdgeInsets.only(bottom: 3.0)),
// Text(
// item.snippet.publishedAt,
// softWrap: true,
// maxLines: 1,
// style: TextStyle(fontSize: 9.0,fontWeight: FontWeight.w300),
// ),
// ]))
// ],
// ),
// ),
// ),
// );
// }
// Widget _buildError(){
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text(c.errorMessage),
// RaisedButton(onPressed: c.refresh, child: Text('Atualizar'),)
// ],
// );
// }
// }
class YouTubeVideosScreen extends StatefulWidget {
@override
_YouTubeVideosScreenState createState() => _YouTubeVideosScreenState();
}
class _YouTubeVideosScreenState extends State<YouTubeVideosScreen> with AutomaticKeepAliveClientMixin<YouTubeVideosScreen> {
final YouTubeController c = Get.put(YouTubeController());
@override
void initState() {
super.initState();
}
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
appBar: AppBar(
title: Text('Vídeos'),
),
body: Obx(() => c.loading.value ? Center(child: CircularProgressIndicator(),) : c.errorCode.value != 0 ? this._buildError() : RefreshIndicator(
onRefresh: c.refresh,
child: AnimationLimiter(
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: c.itens.length + 1,
itemBuilder: (_,index){
if (index < c.itens.length) {
var item = c.itens[index];
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 375),
child: SlideAnimation(
verticalOffset: 30.0,
child: FadeInAnimation(
child: listItem(item),
)
)
);
// return SlideTransition(
// position: c.animation,
// child: this._buildListTile(index)
// );
} else if (index > 1) {
if (!GetUtils.isNullOrBlank(c.results.value.nextPageToken)) {
c.getChannelVideosBloc();
return Center(child: CircularProgressIndicator(),);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.only(top: 8.0,bottom: 25.0),
child:
Text("Não há mais Vídeos para exibir."),
),
);
}
}
else {
return Center(child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text("Não há mais Vídeos para exibir."),
),);
}
},
),
),
)),
);
}
Widget listItem(YouTubeItems item) {
return InkWell(
onTap: (){
if(GetUtils.isNullOrBlank(item.id.videoId)){
Get.rawSnackbar(message: 'Não foi possível reproduzir o vídeo');
}
else{
Get.to(() => YouTubeVideoPlayerScreen(ytVideo: item,));
}
},
child: Card(
elevation: 0,
color: Colors.transparent,
child: Container(
//margin: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
LimitedBox(
maxHeight: 100.0,
child: AspectRatio(
aspectRatio: 4/3,
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: item.snippet?.thumbnails?.thumbDefault?.url ?? '',
fit: BoxFit.cover,
),
),
),
Padding(padding: EdgeInsets.only(right: 10.0)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
item.snippet.title,
softWrap: true,
maxLines: 2,
style: TextStyle(fontSize: 13.0,fontWeight: FontWeight.bold),
),
Padding(padding: EdgeInsets.only(bottom: 1.5)),
Text(
item.snippet.description,
softWrap: true,
maxLines: 3,
style: TextStyle(fontSize: 11.0,fontWeight: FontWeight.w400),
),
Padding(padding: EdgeInsets.only(bottom: 3.0)),
Text(
c.getDateFormatada(item.snippet.publishedAt),
softWrap: true,
maxLines: 1,
style: TextStyle(fontSize: 9.0,fontWeight: FontWeight.w300),
),
]))
],
),
),
),
);
}
Widget _buildError(){
return Container(
width: double.maxFinite,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(c.errorMessage),
RaisedButton(onPressed: c.refresh, child: Text('Atualizar'),)
],
),
);
}
}