This is Part III in a series. Part II added camera functionality onto our app. Part I began by introducing Ionic and setting up our project. Next we’ll continue building out our app by learning about the storage API in Capacitor.
We left off in the previous story having created the camera screen and being able to display the last photo taken. Let’s improve the looks of the Camera screen by adding a Card. Open the Camera.tsx file from the previous project and find the beginning of the JSX return statement. In our current project it should be line 39. Let’s update the file with the following code.
As you can see the buttons now live inside an IonCard component. Inside this component are also the header and content components. Here’s a couple of things to note about components in Ionic. All Ionic components can have two kinds of properties: code properties and CSS properties (same thing as CSS variables). As the name implies code properties can be set within JSX as React props to change style or behavior. CSS properties are variables that have been created in order to change styling of a component. As mentioned previously Ionic components are an aggregation of Web Components and DOM elements. Therefore changing a CSS style on an Ionic component will not necessarily have the desired effect. Let’s see then how we can control styling of components within Ionic. In the Camera.tsx file there is a component called IonCardTitle. Let’s try changing its color to orange. First go to the theme folder and open the variables.css file. Add this style to the file.
Run ionic serve and once the server finishes recompiling you should see that the font color of the component has changed to orange. I’ll clarify what’s happening here. The name of the Web Component is ion-card-title. This is the real name of the component in Stencil and IonCardTitle is the JSX name used only in React. Several CSS variables are associated to this component during its definition. One of those variables is — color. Therefore if we select the ion-card-title component, within our CSS file, and reset the — color property any ion-card-title component will have its color changed. Let’s erase that style and continue.
Now when we take a picture we should see a slightly nicer interface.
So changing only a trivial amount of code we already have a better looking screen. Now let’s save each picture’s name into local storage and move the pics into the app’s directory.
As mentioned in my previous story, Part II, access to native capabilities is given by Capacitor. So we will use Capacitor via Hooks to access local storage. Install the package below, if you did not last time.
npm i @ionic/react-hooks
This package acts as a wrapper to use hooks syntax to access Capacitor plugins. Now that’s installed, let’s modify the Camera.tsx file again to manage the taken image file. First let’s add moment to give us easier date and time formatting.
npm i moment
We’re using moment to dynamically create unique file names, so we have no name clashes when saving file paths later. If you’re not familiar with moment don’t worry as we only use the formatter. To clarify, the meaning of the format “MM-DD-YY-h-mm-ss” is month, day, year, hour, minute, and seconds. And we use that as our file name. Now replace the useEffect function with this code
When a photo is taken the photo immediately gets placed into temporary storage, which may be deleted at any time. Since we want to keep our pictures we need to move them into the app’s own directory, which is what we’re doing here. Filesystem.readFile takes the file from temp and grabs it. Then Filesystem.writeFile takes that file and writes it into the directory of the app. After that Filesystem.getUri gets a system file path for the image. Once that system file path is gotten we use Capacitor.convertFileSrc to change the path into a url style file path since the img tags that we are using cannot read file system paths. Let’s try this Filesystem code on an iPhone. You’ll have to run the following commands to get the updated code into XCode
ionic cap copy ios
ionic cap sync ios
ionic cap open ios
Again these commands are needed because Ionic apps are pure web apps. So we use these command line tools to compile our web code and bring it into our native coding environment, in this case XCode, so that it can be converted into a native app. Now compile and restart the app on your iPhone and take a new picture. You should see the following in the XCode logs.
You can see the file name, the uri file system path, and a url path. Now let’s save our file name and path into local storage so that we can use it again to display in our second screen as a list. I’ve updated the Camera.tsx file and yours should now look like this.
Towards the top you should notice there is a new hook that’s imported, @ionic/react-hooks/storage. This sub directory gives us the useStorage hook, which will grant us the functions to save and get data from local storage. So we update the useEffect function again, and you can see we use get and set calls to retrieve and update our data. Note that this data is only of type string. Therefore if it’s complex data that we have, we need to put it in as JSON string. Once again save, build, and sync these code changes with XCode, with the commands I just showed above, and then let’s run our app again. If you take a picture and look at the log you should see the file’s name logged and an array with just this one file path. Then if you take another picture you should see the second name and then the array grow to two items. And finally let’s shutdown the app and start it up again to see if our data saves across app loads. Now go ahead and take another picture. This time the log should show the latest file name and then an updated paths array with three pictures in it, including the new file. Here’s what I got in my log from this test.
OK I’m going to end it here. In the next story we’ll develop the second tab which will list out thumbnails of our images and allow us to select each one in order to get a full size view. Here’s the updated code.