Navigation

Sunday 13 August 2023

Flutter : Simple Example of State Management with flutter_riverpod

In the world of Flutter app development, efficient state management is a key factor in building responsive and user-friendly applications. With various state management solutions available, developers often find themselves navigating through a maze of options. One solution that has gained significant attention and praise is flutter_riverpod

Project Structure 



Step 1: Install Package

             $ flutter pub add flutter_riverpod 

        Click here to get the latest version


Step 2: Add the following code to your main.dart file.   

The ProviderScope widget, provided by the Riverpod state management framework in Flutter, serves as a container for organizing and managing the state of your application. By wrapping your app's main widget with ProviderScope, you create a controlled environment where you can define and use various state providers seamlessly. This allows you to efficiently manage data across different parts of your app while promoting modularity and reusability.

 void main() {
runApp(const ProviderScope(child: MainApp()));
}

       Below, you'll find the entire code for this page. You can simply copy and paste it as-is:

import 'package:flutter/material.dart';
import 'package:flutter_application_riverpod/home_page.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
  runApp(
    const ProviderScope(child: MainApp()),
  );
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    /// Providers are declared globally and specify how to create a state
    final counterProvider = StateProvider((ref) => 0);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text("RiverPod"),
        ),
        body: const Center(
          child: HomePage(),
        ),
      ),
    );
  }
}


Step 3: home_page.dart 

Please copy and paste the entire code for the "home_page.dart" to ensure you have the complete implementation of the home page.

The provided code exemplifies the use of `flutter_riverpod` for efficient state management in a Flutter app. It showcases a `HomePage` widget, equipped to consume state via Riverpod. Within the widget's state, the `ref.watch(counterProvider)` retrieves and displays the current count value managed by the `counterProvider` state provider. The widget also features an "Increment" button that, when pressed, triggers the `counterProvider`'s `increment` method to increase the count by 2. This concise yet powerful setup illustrates how Riverpod simplifies state management, enabling widgets to access and update app state with ease.



import 'package:flutter/material.dart';
import 'package:flutter_application_riverpod/providers/count_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class HomePage extends ConsumerStatefulWidget {
  const HomePage({super.key});

  @override
  ConsumerState<HomePage> createState() => _HomePageState();
}

class _HomePageState extends ConsumerState<HomePage> {
  @override
  Widget build(BuildContext context) {
    final count = ref.watch(counterProvider);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(count.toString()),
        ElevatedButton(
          onPressed: () {
            ref.read(counterProvider.notifier).increment(2);
          },
          child: const Text(" Count "),
        )
      ],
    );
  }
}


Step 4: Please copy and paste the code from the 'count_provider.dart' file that contains the provider implementation.

The provided code snippet highlights the core elements of `flutter_riverpod` state management. It introduces a `Counter` class that extends `StateNotifier<int>` to manage an integer state, initially set to 0. The class contains an `increment` method that adds a specified value to the state. The `counterProvider` is defined as a `StateNotifierProvider`, creating an instance of `Counter` to manage the state.


import 'package:flutter_riverpod/flutter_riverpod.dart';

class Counter extends StateNotifier<int> {
  Counter() : super(0);
  void increment(int val) => state += val;
}

final counterProvider = StateNotifierProvider((ref) {
  return Counter();
});



To sum it up, `flutter_riverpod` is like a powerful helper for managing how your Flutter app stores and uses information. It makes things easier by organizing data in a neat and organized way. Using `flutter_riverpod`, you can control different parts of your app better, keep your code cleaner, and even share data between different parts of your app more smoothly. Just like a helpful guide on a journey, `flutter_riverpod` takes the stress out of managing your app's data, making your app-building adventure smoother.

Result :


    



Saturday 21 January 2023

Dropbox API: How to download/upload file with Dropbox API

 Step 1: Start by Creating an app as shown in the below image.

Step 2: Give a name to an app like 'TestApp1205' and choose the scope of access as shown in the below image.

Step 3: After selecting an access scop, you have to generate an access token, through which you can get access to the app file and folder. 



Step 4: When the app has been created it looks like this.




Step 5: When file is uploaded with the help of code it looks like the below image.



Step 6: Following are the C# codes to download/upload files.


using Dropbox.Api;
using Dropbox.Api.Files;
using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DropBoxApp
{
    class Program
    {
        public static StreamWriter log;
        //public static string localFilePath = "";

        static void Main(string[] args)
        {
            //localFilePath = Path.GetFullPath("../../../Test");
            Program program = new Program();
            var task = Task.Run((Func<Task>)program.Run);
            task.Wait();          
            Console.WriteLine("Hello World!");
        }
        public async Task Run()
        {

            using (var dbx = new DropboxClient("6exx-HrLsAxxxxTxmSHqbft_YR2Z6xxxxy5GKyHkR4KOM4_w2pGz"))
            {
                log = File.AppendText("logger");
                var full = await dbx.Users.GetCurrentAccountAsync();
                Console.WriteLine("D  {0}", full.Name.DisplayName + "-" + full.Email);
                ListRootFolder(dbx).Wait();
               
            }
        }
      public  async Task ListRootFolder(DropboxClient dbx)
        {
            var list = await dbx.Files.ListFolderAsync(string.Empty);

            // show folders then files
            foreach (var item in list.Entries.Where(i => i.IsFolder))
            {
                Console.WriteLine("D  {0}/", item.Name);
            }
            foreach (var item in list.Entries.Where(i => i.IsFile))
            {
                Console.WriteLine("F{0,8} {1}", item.AsFile.Size, item.Name);
                Download(dbx,"", item.Name).Wait();
            }
        }

     public  async Task Download(DropboxClient dbx, string folder, string file)
        {
            Console.WriteLine("Download file...");

            using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
            {
                Stream StreamFromDropbox = await response.GetContentAsStreamAsync();
                System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
                MemoryStream StreamFromDropboxCopyAsync = new MemoryStream();
                await StreamFromDropbox.CopyToAsync(StreamFromDropboxCopyAsync);
                StreamFromDropboxCopyAsync.Seek(offset: 0, loc: SeekOrigin.Begin);
                IExcelDataReader reader = ExcelDataReader.ExcelReaderFactory
.CreateOpenXmlReader(StreamFromDropboxCopyAsync,
new ExcelReaderConfiguration()
{ FallbackEncoding = System.Text.Encoding.GetEncoding(1252) });
               
                //Value store in dataset
                DataSet ds = reader.AsDataSet();

                Console.WriteLine("Downloaded {0} Rev {1}", response.Response.Name, response.Response.Rev);

                //Console.WriteLine("------------------------------");
                //Console.WriteLine(await response.GetContentAsStringAsync());
                //Console.WriteLine("------------------------------");
            }          
           
        }

       //public async Task Upload(DropboxClient dbx, string folder, string file, string content)
       // {
       //     using (var mem = new MemoryStream(Encoding.UTF8.GetBytes(content)))
       //     {
       //         var updated = await dbx.Files.UploadAsync(
       //             folder + "/" + file,
       //             WriteMode.Overwrite.Instance,
       //             body: mem);
       //         Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
       //     }
       // }
    }
}


Some other methods to call Dropbox API 

using Dropbox.Api;
using Dropbox.Api.Common;
using Dropbox.Api.Files;
using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace DropBoxApp
{
    class Program
    {
        public static StreamWriter log;
        //public static string localFilePath = "";

        static void Main(string[] args)
        {
            //localFilePath = Path.GetFullPath("../../../Test");
            Program program = new Program();
            var task = Task.Run((Func<Task>)program.Run);
            task.Wait();          
            Console.WriteLine("Hello World!");
        }
        private async Task<FolderMetadata> CreateFolder(DropboxClient client, string path)
        {
            Console.WriteLine("--- Creating Folder ---");
            var folderArg = new CreateFolderArg(path);
            try
            {
                var folder = await client.Files.CreateFolderV2Async(folderArg);

                Console.WriteLine("Folder: " + path + " created!");

                return folder.Metadata;
            }
            catch (ApiException<CreateFolderError> e)
            {
                if (e.Message.StartsWith("path/conflict/folder"))
                {
                    Console.WriteLine("Folder already exists... Skipping create");
                    return null;
                }
                else
                {
                    throw e;
                }
            }
        }

        public async Task Run()
        {

            using (var dbx = new DropboxClient("6exx-HrLsAxxxxTxmSHqbft_YR2Z6xxxxy5GKyHkR4KOM4_w2pGz"))
            {
                log = File.AppendText("logger");
                await  GetCurrentAccount(dbx);
                //var full = await dbx.Users.GetCurrentAccountAsync();
                //Console.WriteLine("D  {0}", full.Name.DisplayName + "-" + full.Email);
                //ListRootFolder(dbx).Wait();

                var path = "/EventId";
                var folder = await CreateFolder(dbx, path);
                var list = await ListFolder(dbx, path);

                var firstFile = list.Entries.FirstOrDefault(i => i.IsFile);
                if (firstFile != null)
                {
                    await Download(dbx, path, firstFile.AsFile);
                }
                //var pathInTeamSpace = "/Test";
                //await ListFolderInTeamSpace(dbx, pathInTeamSpace);                
                await Upload(dbx, path, firstFile.AsFile, "This is a text file");
                //await ChunkUpload(dbx, path, "Binary");

            }
        }
        private async Task GetCurrentAccount(DropboxClient client)
        {
            var full = await client.Users.GetCurrentAccountAsync();

            Console.WriteLine("Account id    : {0}", full.AccountId);
            Console.WriteLine("Country       : {0}", full.Country);
            Console.WriteLine("Email         : {0}", full.Email);
            Console.WriteLine("Is paired     : {0}", full.IsPaired ? "Yes" : "No");
            Console.WriteLine("Locale        : {0}", full.Locale);
            Console.WriteLine("Name");
            Console.WriteLine("  Display  : {0}", full.Name.DisplayName);
            Console.WriteLine("  Familiar : {0}", full.Name.FamiliarName);
            Console.WriteLine("  Given    : {0}", full.Name.GivenName);
            Console.WriteLine("  Surname  : {0}", full.Name.Surname);
            Console.WriteLine("Referral link : {0}", full.ReferralLink);

            if (full.Team != null)
            {
                Console.WriteLine("Team");
                Console.WriteLine("  Id   : {0}", full.Team.Id);
                Console.WriteLine("  Name : {0}", full.Team.Name);
            }
            else
            {
                Console.WriteLine("Team - None");
            }
        }
        //private async Task RunUserTests(DropboxClient client)
        //{
        //    await GetCurrentAccount(client);

        //    //var path = "/DotNetApi/Help";
        //    //var folder = await CreateFolder(client, path);
        //    //var list = await ListFolder(client, path);

        //    //var firstFile = list.Entries.FirstOrDefault(i => i.IsFile);
        //    //if (firstFile != null)
        //    //{
        //    //    await Download(client, path, firstFile.AsFile);
        //    //}

        //    //var pathInTeamSpace = "/Test";
        //    //await ListFolderInTeamSpace(client, pathInTeamSpace);

        //    //await Upload(client, path, "Test.txt", "This is a text file");

        //    //await ChunkUpload(client, path, "Binary");
        //}
        //public  async Task ListRootFolder(DropboxClient dbx)
        //{
        //    var list = await dbx.Files.ListFolderAsync(string.Empty);

        //    // show folders then files
        //    foreach (var item in list.Entries.Where(i => i.IsFolder))
        //    {
        //        Console.WriteLine("D  {0}/", item.Name);
        //    }
        //    foreach (var item in list.Entries.Where(i => i.IsFile))
        //    {
        //        Console.WriteLine("F{0,8} {1}", item.AsFile.Size, item.Name);
        //        //Download(dbx,"", item.Name).Wait();
        //    }
        //}
        private async Task<ListFolderResult> ListFolder(DropboxClient client, string path)
        {
            Console.WriteLine("--- Files ---");
            var list = await client.Files.ListFolderAsync(path);

            // show folders then files
            foreach (var item in list.Entries.Where(i => i.IsFolder))
            {
                Console.WriteLine("D  {0}/", item.Name);
            }

            foreach (var item in list.Entries.Where(i => i.IsFile))
            {
                var file = item.AsFile;

                Console.WriteLine("F{0,8} {1}",
                    file.Size,
                    item.Name);
            }

            if (list.HasMore)
            {
                Console.WriteLine("   ...");
            }
            return list;
        }
        private async Task Download(DropboxClient client, string folder, FileMetadata file)
        {
            Console.WriteLine("Download file...");

            using (var response = await client.Files.DownloadAsync(folder + "/" + file.Name))
            {
                Console.WriteLine("Downloaded {0} Rev {1}", response.Response.Name, response.Response.Rev);
                Console.WriteLine("------------------------------");
                Stream StreamFromDropbox = await response.GetContentAsStreamAsync();
                SaveFileStream(folder, StreamFromDropbox, response.Response.Name);
                Console.WriteLine("------------------------------");
            }
        }
        private void SaveFileStream(string path, Stream stream,string fileName)
        {
            string localFilePath = Path.GetFullPath("../../../"+path+"/"+fileName);
            var fileStream = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
            stream.CopyTo(fileStream);
            fileStream.Dispose();
        }
        private async Task Upload(DropboxClient client, string folder, FileMetadata file, string fileContent)
        {
            Console.WriteLine("Upload file...");
            string NewFileName = DateTime.Now.ToString("ddMMyyyymmss") + "_" + file.Name;
            string str = folder + "/" + NewFileName;
           
            string localFilePath = Path.GetFullPath("../../../EventId/" + file.Name);

            FileStream fs = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
            byte[] tmpBytes = new byte[fs.Length];
            fs.Read(tmpBytes, 0, Convert.ToInt32(fs.Length));
            //MemoryStream mystream = new MemoryStream(tmpBytes);

            using (var stream = new MemoryStream(tmpBytes))
            {
                var response = await client.Files.UploadAsync(folder + "/" + NewFileName, WriteMode.Overwrite.Instance, body: stream);

                Console.WriteLine("Uploaded Id {0} Rev {1}", response.Id, response.Rev);
            }
        }
        private async Task ChunkUpload(DropboxClient client, string folder, string fileName)
        {
            Console.WriteLine("Chunk upload file...");
            // Chunk size is 128KB.
            const int chunkSize = 128 * 1024;

            // Create a random file of 1MB in size.
            var fileContent = new byte[1024 * 1024];
            new Random().NextBytes(fileContent);

            using (var stream = new MemoryStream(fileContent))
            {
                int numChunks = (int)Math.Ceiling((double)stream.Length / chunkSize);

                byte[] buffer = new byte[chunkSize];
                string sessionId = null;

                for (var idx = 0; idx < numChunks; idx++)
                {
                    Console.WriteLine("Start uploading chunk {0}", idx);
                    var byteRead = stream.Read(buffer, 0, chunkSize);

                    using (MemoryStream memStream = new MemoryStream(buffer, 0, byteRead))
                    {
                        if (idx == 0)
                        {
                            var result = await client.Files.UploadSessionStartAsync(body: memStream);
                            sessionId = result.SessionId;
                        }

                        else
                        {
                            UploadSessionCursor cursor = new UploadSessionCursor(sessionId, (ulong)(chunkSize * idx));

                            if (idx == numChunks - 1)
                            {
                                await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(folder + "/" + fileName), memStream);
                            }

                            else
                            {
                                await client.Files.UploadSessionAppendV2Async(cursor, body: memStream);
                            }
                        }
                    }
                }
            }
        }
        private async Task ListFolderInTeamSpace(DropboxClient client, string path)
        {
            // Fetch root namespace info from user's account info.
            var account = await client.Users.GetCurrentAccountAsync();

            if (!account.RootInfo.IsTeam)
            {
                Console.WriteLine("This user doesn't belong to a team with shared space.");
            }
            else
            {
                try
                {
                    // Point path root to namespace id of team space.
                    client = client.WithPathRoot(new PathRoot.Root(account.RootInfo.RootNamespaceId));
                    await ListFolder(client, path);
                }
                catch (PathRootException ex)
                {
                    Console.WriteLine(
                        "The user's root namespace ID has changed to {0}",
                        ex.ErrorResponse.AsInvalidRoot.Value);
                }
            }
        }

        //public async Task Download(DropboxClient dbx, string folder, string file)
        //{
        //    Console.WriteLine("Download file...");

        //    using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
        //    {
        //        Stream StreamFromDropbox = await response.GetContentAsStreamAsync();
        //        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
        //        MemoryStream StreamFromDropboxCopyAsync = new MemoryStream();
        //        await StreamFromDropbox.CopyToAsync(StreamFromDropboxCopyAsync);
        //        StreamFromDropboxCopyAsync.Seek(offset: 0, loc: SeekOrigin.Begin);
        //        IExcelDataReader reader = ExcelDataReader.ExcelReaderFactory.CreateOpenXmlReader(StreamFromDropboxCopyAsync, new ExcelReaderConfiguration() { FallbackEncoding = System.Text.Encoding.GetEncoding(1252) });

        //        //Value store in dataset
        //        DataSet ds = reader.AsDataSet();

        //        Console.WriteLine("Downloaded {0} Rev {1}", response.Response.Name, response.Response.Rev);

        //        //Console.WriteLine("------------------------------");
        //        //Console.WriteLine(await response.GetContentAsStringAsync());
        //        //Console.WriteLine("------------------------------");
        //    }

        //    //using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
        //    //{
        //    //     string _file = await response.GetContentAsStringAsync();

        //    //    //Console.WriteLine(await response.GetContentAsStringAsync());
        //    //}
        //}

        //public async Task Upload(DropboxClient dbx, string folder, string file, string content)
        // {
        //     using (var mem = new MemoryStream(Encoding.UTF8.GetBytes(content)))
        //     {
        //         var updated = await dbx.Files.UploadAsync(
        //             folder + "/" + file,
        //             WriteMode.Overwrite.Instance,
        //             body: mem);
        //         Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
        //     }
        // }
    }
}

Friday 20 January 2023

Angular: An autocomplete/fuzzy search in textbox

Fuzzy search is more powerful than exact searching when used for approximate string matching and investigation. Fuzzy search is very useful when researching unfamiliar words.


Step 1: Please copy and paste the following code to your HTML page as shown below app.component.html



<h1>{{title}}</h1>
<div class="col-md-3">
    <div class="form-group">
      <label for="empid" class="bmd-label-floating"> Search User</label>
      <input type="text" class="form-control" [(ngModel)]="txtUserName"
        (keyup)="searchUser(txtUserName)" >      
      <div class="autocomplete" *ngIf="flag">
        <div id="myInputautocomplete-list" class="autocomplete-items">
          <div *ngFor="let usr of searchTerms" (click)="onselectUser(usr.name)">
            {{usr.name}}
            <br />
          </div>
        </div>
      </div>
    </div>
  </div>


Step 2: After the HTML code here is the TS code of the same page  app.component.ts.


import { Component, OnInit } from '@angular/core';
import { ApiService } from './api.service';
import { FormBuilder } from '@angular/forms';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'Fuzzy Search Example';
  public UserLst: any[] = [];
  searchTerms: any[]=[];
  flag: boolean=false;
  txtUserName: string="";
  constructor(private _apiService: ApiService,
    private formBuilder: FormBuilder,
  ) { }

  ngOnInit() {
    this._apiService.getUser().subscribe(res =>{
      this.UserLst = res;
    });
  }
  searchUser(value: string): void {  
    debugger;
    this.flag = true;  
    this.searchTerms = this.UserLst.filter(
      item => item.name.toLowerCase().indexOf(value.toLowerCase()) > -1)
  }  
  onselectUser(Obj:any):boolean{  
    debugger;  
    this.txtUserName = ""
    if (Obj.name != "") {  
      this.flag = false;
      this.txtUserName = Obj;  
      return true;
    }  
    else {  
      return false;  
    }  
  }
}


Step 3: For the proper view of the search following CSS is required. You can change it according to your requirements. app.component.css

.autocomplete {
    position: relative;
    display: inline-block;
    width:80%;
  }   
 
  .autocomplete-items {
    position: absolute;
    border: 1px solid #d4d4d4;
    border-bottom: none;
    border-top: none;
    z-index: 99;
    /*position the autocomplete items to be the same width as the container:*/
    top: 100%;
    left: 0;
    right: 0;
    max-height: 200px;
    overflow: auto;
  }
 
  .autocomplete-items div {
    padding: 10px;
    cursor: pointer;
    background-color: #fff;
    border-bottom: 1px solid #d4d4d4;    
  }
  .autocomplete-items a {
    text-decoration: none !important;
  }
  /*when hovering an item:*/
  .autocomplete-items div:hover {
    background-color: #81c7f0;
  }
 
  /*when navigating through the items using the arrow keys:*/
  .autocomplete-active {
    background-color: DodgerBlue !important;
    color: #ffffff;
  }


Step 4: To get the user list from API you have to add one service file like in this project I have used. api.service.ts


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
  providedIn: 'root'
})
export class ApiService {

  private BASE_API_URL = "https://gorest.co.in/public/";


  private _controllerName: string = "v2/";
  private _url: string = this.BASE_API_URL + this._controllerName;
  private _methodName: string = "";

  private _param:any={}; 
  private httpOptions = {
    _headers: new HttpHeaders({
      'Content-Type': 'applicantion/json'
    })
  };
  constructor(private _http: HttpClient) {

    console.log('Hello Service Provider');
  }
  getUser(): Observable<any[]> {
    this._methodName = "users/"
    return this._http.get<any[]>(this._url + this._methodName);
  }
}


 Step 5: app.module.ts file has the following component that is required for this project.


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule      
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }




and in the last image, you can see the complete structure of the project.



You can also use this angular-ng-autocomplete