Show/Open picture from list that has been provided by dropbox api

#1

Hi there,

for my university project I created an ionic app with help from this tutorial:

Everything that is described in this tutorial works fine in my app. I used the exact same code.
I am getting a list of files (in my case pictures) from that app folder I created on the dropbox developer website over the API.


Now having the list with all the files from the public app folder I would like to show/open the pictures (.jpg files) by tapping on the picture. therefore I created a button item in the home.html.
I also tried to link this button with a “open file()”-function but it doesn’t work… I am not very sophisticated in programming with ionic or programming in general.
Unfortunately, I have no clue how to get the picture being shown by tapping on it.
I know there’s a special viewer plugin for ionic that might help but I could not get this one to work either.

Is there any similar solution to that problem yet or can someone help?

Best regards,
Carina

#2

Does the API response any url? if so you can send it on your open image function openImage(file.url) and probably show this image in a modal, with <img src="">

In your home.ts

openImage(url_image){
  let imageModal= this.modalCtrl.create(CaseboardModalFilterPage, { imgUlr: url_image});
  imageModal.onDidDismiss((data) => {
     // Some action if you want
  });
  imageModal.present();
}

in your modal-image-page.ts

imgUlr: string;
constructor(
    public navParams: NavParams
    public viewCtrl: ViewController,
  ) {
    this.imgUlr= this.navParams.get('imgUlr');
  }

in your modal-image-page.html

<ion-content>
  <img src=“{{imgUlr}}”>
<ion-content>
#3

Thanks for the quick answer!
And sorry for my question - I am a newbie:

Could you tell me how to get the first snippet work without any errors? It still doesn’t recognize the “CaseboardModalFilterPage” (see screenshot below). Do I need to import it first?

And the other question is where I need to put the next two snippets (modal-image-page). I have home.ts and home.html and a login-page.ts and login-page.html handling the authentication for dropbox and a dropbox.ts which is handling all the getlist and folder-functions.

Sorry again.

Best regards,
Carina

#4

This is the documentation of the Modal controllers, check it first.

Im sorry i just copy a code what i have.
Create a new page, ionic g page modal-image (the comman to generate pages) is to possible that you have to add the modal-image-page on your imports at app.modules.ts file.

https://www.techiediaries.com/ionic-modals/ this is a good example, follow it if you have any question let me know.

Also, the dropbox Api respond with a folder of file url? if not this wont work.

Basically you need to create a new page, and use it as the modal page.

#5

Thank you so far! Now I finally got the point where the code has no errors anymore.
Opening pictures still doesn’t work. That’s probably because I would need the “gettemporarylink”-solution from dropbox api which says I am supposed to use this URL:

Do you know where exactly in my code I have to insert this gettemporarylink URL?

#6

Can someone help with the temporary link?


This function doesn’t work. I am pretty sure there is something missing.

#7

You have to call dropbox API first to get the link sending as parameter the file path then use the api response to open the InAppBrowser with the real temporary link, iab wil not undestand that you want to open some file, following a little bit the totorial this could be like this:

home.ts

<ion-header>
<ion-navbar color="primary">
    <ion-title>
    Ionic 2 Dropbox
    </ion-title>
    <ion-buttons start>
    <button ion-button *ngIf="depth" (click)="goBack()"><ion-icon name="arrow-back"></ion-icon> Back</button> 
    </ion-buttons>
</ion-navbar>
</ion-header>

<ion-content>

    <ion-list>
        <div *ngFor="let folder of folders">
        <ion-item *ngIf="folder['.tag'] == 'folder'" detail-push (click)="openFolder(folder.path_lower)">
            {{folder.name}}
        </ion-item>
        <ion-item *ngIf="folder['.tag'] == 'file'" (click)="openFile(folder.path_lower)">
            {{folder.name}}
        </ion-item>
        </div>
    </ion-list>

</ion-content>

home.ts

openFile(path){
    let loading = Loading.create({
        content: 'Syncing from Dropbox...'
    });
    this.nav.present(loading);

    this.dropbox.getTemporaryLink(path).subscribe(data => {
        this.iab.create(data.link, "_system");
        loading.dismiss();
    }, err => {
    console.log(err);
        loading.dismiss();
    });
}

and in your dropbox.ts

getTemporaryLink(path?){
    let headers = new Headers();

    headers.append('Authorization', 'Bearer ' + this.accessToken);
    headers.append('Content-Type', 'application/json');
 

    return this.http.post('https://api.dropboxapi.com/2/files/get_temporary_link', {"path": path }, {headers: headers})
      .map(res => res.json());

  }
}

Hope this helps.

#8

Hey, thank you. I implemented the code you’ve written and I am getting at least to the step where the message “syncing from dropbox” appears when I click on one picture from the list. but unfortunately the picture is now being shown. dropbox is propably not able to handle the correct link to the file I am tapping on.

So, is it possible to just show a picture I set up a static link to in my code?
Like this:

Therefore I need to delete the “path” variable from “getTemporaryLink(path?)” and also in the “openFile()”-function, right? I did that hoping it is showing me that one picture but it doesn’t.

Do you maybe have an idea?

#9

No, that variable is sending the path on dropbox, so thats why i sending that and reciving on those functions. there is no way that the get temporary function know what file shoud show.

Post your dropbox.ts, home.ts, home.html so i can see if you are doing okay.

if you have this code on github send me the link so i can checkit.

Btw sry for my bad english.

#10

Your English is great. I am also no native english speaker :wink: and as long as communication is working, everything is more than fine :smiley:
So here’s the code I got so far:

home.html:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      NZ Pictures
    </ion-title>
    <ion-buttons start>
      <button ion-button *ngIf="depth" (click)="goBack()"><ion-icon name="arrow-back"></ion-icon> Back</button>
    </ion-buttons>
  </ion-navbar>
</ion-header>
 
<ion-content>
 
  <ion-list>
    <div *ngFor="let folder of folders">
      <ion-item *ngIf="folder['.tag'] == 'folder'" detail-push (click)="openFolder(folder.path_lower)">
        {{folder.name}}
      </ion-item>
      <button ion-item *ngIf="folder['.tag'] == 'file'" (click)="openFile(folder.path_lower)">
        {{folder.name}}
      </button>
    </div>
  </ion-list>

</ion-content>

home.ts:

import { Component } from '@angular/core';
import { NavController, LoadingController, AlertController, Platform, ModalController, Modal, } from 'ionic-angular';
import { Dropbox } from '../../providers/dropbox/dropbox';
import { InAppBrowser } from '@ionic-native/in-app-browser';
import { FileOpener } from '@ionic-native/file-opener';
import { FileChooser } from '@ionic-native/file-chooser';
import { FilePath } from '@ionic-native/file-path';
import { Http, Headers } from '@angular/http';

import { LocalNotifications } from '@ionic-native/local-notifications';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
 
  depth: number = 0;
  folders: any;
 
  constructor(public http: Http, public iab: InAppBrowser, public modalCtrl: ModalController, private fileChooser: FileChooser, public alertCtrl: AlertController, private fileOpener: FileOpener, private filePath: FilePath, public navCtrl: NavController, public dropbox: Dropbox, public loadingCtrl: LoadingController, private plt: Platform, private localNotifications: LocalNotifications) {
  }
 
  ionViewDidLoad(){
 
      
      this.folders = [];
 
      let loading = this.loadingCtrl.create({
        content: 'Syncing from Dropbox...'
      });
 
      loading.present();
 
      this.dropbox.getFolders().subscribe(data => {
        this.folders = data.entries;
        loading.dismiss();
      }, (err) => {
        console.log(err);
      });

      this.localNotifications.schedule({
        title: 'Attention',
        text: 'New pictures online!',
        sound: null
            });
 
  }

  ionViewDidEnter(){
 
    let loading = this.loadingCtrl.create({
      content: 'Syncing from Dropbox...'
    });
   
    loading.present();
   
    this.dropbox.getFolders().subscribe(data => {
      this.folders = data.entries;
      loading.dismiss();
    }, (err) => {
      console.log(err);
    });
   
  }
 
  openFolder(path){
 
    let loading = this.loadingCtrl.create({
      content: 'Syncing from Dropbox...'
    });

    loading.present();
   
    this.dropbox.getFolders(path).subscribe(data => {
      this.folders = data.entries;
      this.depth++;
      loading.dismiss();
    }, err => {
      console.log(err);
    });
   
  }
 
  goBack(){
 
    let loading = this.loadingCtrl.create({
      content: 'Syncing from Dropbox...'
    });

    loading.present();
   
    this.dropbox.goBackFolder().subscribe(data => {
      this.folders = data.entries;
      this.depth--;
      loading.dismiss();
    }, err => {
      console.log(err);
    });
   
  }

  scheduleNotification(){
    //this.plt.ready().then(() => {
    this.localNotifications.schedule({
      title: 'Attention',
      text: 'New pictures online!',
      sound: null
          });
    //});
  }


openFile(path){
  let loading = this.loadingCtrl.create({
    content: 'Syncing from Dropbox...'
  });

    loading.present();


    this.dropbox.getTemporaryLink().subscribe(data => {
      this.iab.create(data.link, '_system', 'location=yes');
      loading.dismiss();

    }, err => {
      console.log(err);
      loading.dismiss();
    });
    
  }
}

dropbox.ts:

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
 
//part 2
import { InAppBrowser } from '@ionic-native/in-app-browser';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class Dropbox {
 
  accessToken: any;
  folderHistory: any = [];
  appKey: any;
  redirectURI: any;
  url: any;
   
  constructor(public http: Http, public iab: InAppBrowser ) {
   
      //OAuth
      this.appKey = '***myAppKey***';
      this.redirectURI = 'http://localhost';
      this.url = 'https://www.dropbox.com/1/oauth2/authorize?client_id=' + this.appKey + '&redirect_uri=' + this.redirectURI + '&response_type=token';
   
  }
 
  setAccessToken(token) {
    this.accessToken = token;
  }
 
  getUserInfo(){
 
    let headers = new Headers();
   
    headers.append('Authorization', 'Bearer ' + this.accessToken);
    headers.append('Content-Type', 'application/json');
   
    return this.http.post('https://api.dropboxapi.com/2/users/get_current_account', "null", {headers: headers})
      .map(res => res.json());
   
  }
 
  getFolders(path?){
 
    let headers = new Headers();
   
    headers.append('Authorization', 'Bearer ' + this.accessToken);
    headers.append('Content-Type', 'application/json');
   
    let folderPath;
   
    if(typeof(path) == "undefined" || !path){
   
      folderPath = {
        path: ""
      };   
   
    } else {
   
      folderPath = {
        path: path
      };
   
      if(this.folderHistory[this.folderHistory.length - 1] != path){
        this.folderHistory.push(path);
      }
   
    }
   
    return this.http.post('https://api.dropboxapi.com/2/files/list_folder', JSON.stringify(folderPath), {headers: headers})
      .map(res => res.json());
   
  }
 
  goBackFolder(){
 
    if(this.folderHistory.length > 0){
   
      this.folderHistory.pop();
      let path = this.folderHistory[this.folderHistory.length - 1];
   
      return this.getFolders(path);
    }
    else {
      return this.getFolders();
    }
  }

 
  login(){
 
    return new Promise((resolve, reject) => {
   
      let browser = this.iab.create(this.url, '_blank');
   
      let listener = browser.on('loadstart').subscribe((event: any) => {
   
        //Ignore the dropbox authorize screen
        if(event.url.indexOf('oauth2/authorize') > -1){
          return;
        }
   
        //Check the redirect uri
        if(event.url.indexOf(this.redirectURI) > -1 ){
          listener.unsubscribe();
          browser.close();
          let token = event.url.split('=')[1].split('&')[0];
          this.accessToken = token;
          resolve(event.url);
        } else {
          reject("Could not authenticate");
        }
   
      });
   
    });
   
  }

getTemporaryLink(path?){
  let headers = new Headers();

  headers.append('Authorization', 'Bearer' + this.accessToken);
  headers.append('Content-Type', 'application/json');

  return this.http.post('https://api.dropboxapi.com/2/files/get_temporary_link', {"path": path }, {headers: headers})

      .map(res => res.json());
  }

}
#11

Send here the path that you recive on the openFile(path) function

this.dropbox.getTemporaryLink(path).subscribe(data => {

Just in case remove the ? at the end of path on the getTemporaryLink funtion

getTemporaryLink(path){

Also add a console.log and see in the console what response returns dropbox api.

In your home.ts at the

this.dropbox.getTemporaryLink(path).subscribe(data => {
{
      console.log(data);
      this.iab.create(data.link, '_system', 'location=yes');
      loading.dismiss();
}, err => {
      console.log(err);
      loading.dismiss();
});
#12

I implemented your suggestions in my code but it still doesn’t show the picture I am tapping on.
The problem is that this code (if you are following the instructions in the tutorial from Josh Morony) is known as only working in the app itself. when I try to get a preview with “ionic serve” it always says that localhost is not available. so I can not track down the responses the console is giving.
Or do I have the possibility to see what dropbox api is responding on my smartphone?

#13

Debug the app then.
if you are in a Mac follow this instructions: https://moduscreate.com/blog/enable-remote-web-inspector-in-ios-6/
if you are in windows https://raygun.com/blog/debug-android-chrome/
Is more easy on windows with android.

Check the console for errors.