miércoles, 31 de marzo de 2021

Flutter: StreamBuilder, Pull To Refresh, Pagination

#1

https://medium.com/flutterdevs/pagination-in-flutter-with-firebase-firestore-96d6cc11aef2

#2

#3

https://www.udemy.com/course/flutter-ios-android-fernando-herrera/learn/lecture/14478706#overview

Mi resultado

Esta es mi adaptación aplicada al video anterior + el video 110 StreamBuilder (De la sección 7 Aplicación de películas, del curso de Udemy, flutter-ios-android-fernando-herrera) (ese video es privado) + el tutorial de flutterdevs.

Paginar desde Firebase functions https://fireship.io/lessons/firestore-pagination-guide

const admin = require('firebase-admin');
const pageThree = ref.orderBy(field).limit(10).offset(20);

List view


class DatabasePage extends StatefulWidget {

  static final String routeName = 'pagename';

  @override

  _DatabasePageState createState() => _DatabasePageState();

}


class _DatabasePageState extends State<DatabasePage> {

  ProductsProvider productsProvider = new ProductsProvider();

  ScrollController controller = ScrollController();

  ProductListBloc productListBloc;


  @override

  void initState() {

    super.initState();

    productListBloc = ProductListBloc();

    productListBloc.fetchNextProducts();

    controller.addListener(_scrollListener);

  }


  void _scrollListener() {

    if (controller.offset >= controller.position.maxScrollExtent &&

        !controller.position.outOfRange) {

      print("at the end of list");

      productListBloc.fetchNextProducts();

    }

  }


  @override

  void dispose() {

    productListBloc.dispose();

    super.dispose();

  }


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: Text('T I T L E'),

        backgroundColor: Color.fromRGBO(92, 171, 115, 50),

        actions: <Widget>[

          IconButton(

            icon: Icon(Icons.add),

            color: Colors.white,

            onPressed: () =>

                Navigator.pushNamed(context, ProductFormPage.routeName)

                    .then((value) {

              setState(() {});

            }),

          )

        ],

      ),

      body: _createList(),

    );

  }


  Widget _createList() {

    return StreamBuilder(

      stream: productListBloc.productStream,

      builder:

          (BuildContext context, AsyncSnapshot<List<ProductModel>> snapshot) {

        if (snapshot.hasData) {

          return ListView.builder(

            controller: controller,

            itemCount: snapshot.data.length + 1,

            itemBuilder: (BuildContext context, int index) {

              if (index < snapshot.data.length) {

                return _createItem(context, snapshot.data[index]);

              } else if (productListBloc.hasMore) {

                return Padding(

                  padding: EdgeInsets.symmetric(vertical: 32.0),

                  child: Center(child: CircularProgressIndicator()),

                );

              } else {

                return Padding(

                  padding: EdgeInsets.symmetric(vertical: 32.0),

                  child: Center(child: Text('Fin de la lista.')),

                );

              }

            },

          );

        } else {

          return Center(child: CircularProgressIndicator());

        }

      },

    );

  }


  Widget _createItem(BuildContext context, ProductModel item) {

    Widget content = ...

    ...

    ...

    ...

    

    return content;

  }


}


BLoC


class ProductListBloc {

  List<ProductModel> documentList = [];

  ProductsProvider productsProvider;

  bool hasMore = true;


  StreamController<List<ProductModel>> _streamController;


  ProductListBloc() {

    _streamController = StreamController<List<ProductModel>>();

    productsProvider = new ProductsProvider();

    hasMore = true;

  }


  Stream<List<ProductModel>> get productStream => _streamController.stream;


  /*This will automatically fetch the next 10 elements from the list*/

  fetchNextProducts() async {

    try {

      List<ProductModel> newDocumentList = (await productsProvider.retrieve(documentList.length));

      documentList.addAll(newDocumentList);

      _streamController.sink.add(documentList);

      hasMore = newDocumentList.length == 30/*page size from backend*/;

    } on SocketException {

      _streamController.sink.addError(SocketException("No Internet Connection"));

    } catch (e) {

      print(e.toString());

      _streamController.sink.addError(e);

    }

  }


  void dispose() {

    _streamController.close();

  }

}


sábado, 9 de enero de 2021

CocoaPods could not find compatible versions for pod "FirebaseFirestore"

Seguiste la guía oficial de FlutterFire https://firebase.flutter.dev/docs/overview/#improve-ios-build-times Donde te dice que agregues esta línea a ios/Podfile

  • pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.26.0'

Instalaste Cocoapods https://josevibriezca.blogspot.com/2021/01/instalar-cocoapods-en-macos-1015.html

Y ahora tienes un nuevo error:

  • [!] CocoaPods could not find compatible versions for pod "FirebaseFirestore":
    • In Podfile:
      • FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `6.26.0`)
      • cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`) was resolved to 0.14.4, which depends on
        • Firebase/Firestore (~> 6.33.0) was resolved to 6.33.0, which depends on
          • FirebaseFirestore (~> 1.18.0)

El problema esta en que tenemos instalada una versión diferente a la que especificamos en Pofdile

Para solucionarlo vamos al archivo Podfile (que está en la carpeta ios) del proyecto de Flutter y cambiamos:

  • pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.26.0'

por 6.33.0 (o cualquiera que sea la versión que el error nos indique – en mi caso me dice was resolved to 6.33.0)

  • pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.33.0'

Instalar cocoapods en macOS 10.15 Catalina

Tienes un proyecto en Flutter con Firebase y en Windows+Android funciona todo bien. Cuando lo intentas ejecutar en macOS con el emulador de iPhone falla porque no tienes Cocoapods instalado.

Al tratar de instalar cocoapods desde la terminal con el comando:

sudo gem install cocoapods

La instalación falla con los errores:

  • Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.
  • /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:467:in `try_do': The compiler failed to generate an executable file. (RuntimeError) You have to install development tools first.

Después de mucho googlear y que nada funciono, la respuesta la encontré en una pregunta de un curso de Fernando Herrera, gracias al alumno Alejandro César Valencia.

La solución está en https://www.udemy.com/course/flutter-ios-android-fernando-herrera/learn/lecture/14717920#questions/12534056 pero no podrás verla si no compraste el curso. A continuación, comparto la solución de Alejandro y si les sirve no se olviden de comprar el curso de Fernando que está muy bueno y agradecer a Alejandro.

  1. Actualiza Ruby a la última versión (en mi caso fue la 2.7.2). Teclea en la terminal:
    • curl -L https://get.rvm.io | bash -s stable
  2. Reinicia la terminal (clic derecho salir y vuelve a abrir)
  3. Ejecuta:
    • rvm install ruby-[version]
    Reemplaza versión por la más actual (sin los corchetes). Esto se tarda un rato.
    (o quita -[version] si no quieres especificar una versión)
  4. Ya que termina de instalar Ruby, ahora instala cocoapods:
    • sudo gem install cocoapods
    y listo. una vez que termine verifica con:
    • pod --version

lunes, 23 de noviembre de 2020

Dar formato a código HTML en NotePad++

Bueno como ya tiene mucho que no uso Dreamweaver aquí esta una versión más reciente de mi entrada antigua (Dar formato al código en Dreamweaver)
  • Menú Plugins / Plugins admin
  • Buscar e instalar XML Tools
  • Presionar la combinación de teclas Ctrl+Alt+Shift+B

viernes, 7 de febrero de 2020

Dynamics 365 - Consult TracingService logs

Steps to follow if you want to view log made by plugins with TracingService. Example:
serviceContext.TracingService.Trace("Test");

  1. Navigate to Settings > Administration > System Settings.
  2. Click Customization tab and locate the drop-down “Enable logging to plug-in trace log” and select “Exceptions” or “All” depending on what you need. Click OK.
  3. Run the plugin.
  4. Navigating to Settings > Plug-in Trace Log.

Dynamics 365 - Debug Plugin using Plugin Registration tool

I found this video on the youTube channel Magnifez Technologies

Dynamics 365 - Plugin development step by step

I found this interesting video on YouTube.