<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Raul Riera on Medium]]></title>
        <description><![CDATA[Stories by Raul Riera on Medium]]></description>
        <link>https://medium.com/@raulriera?source=rss-8501090bb2de------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*7iZcJlNb9GQoBsCsSxC0lw.png</url>
            <title>Stories by Raul Riera on Medium</title>
            <link>https://medium.com/@raulriera?source=rss-8501090bb2de------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 24 Apr 2026 03:46:51 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@raulriera/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[I rebuilt Claude Desktop in 10 days. Here’s why.]]></title>
            <link>https://raulriera.medium.com/i-rebuilt-claude-desktop-in-10-days-heres-why-2efb47133da9?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/2efb47133da9</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[mac]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Wed, 18 Mar 2026 16:28:44 GMT</pubDate>
            <atom:updated>2026-03-18T16:28:44.693Z</atom:updated>
            <content:encoded><![CDATA[<p>A few weeks ago, I came across a tweet about Cowork, Anthropic’s own tool built in just 10 days. I thought, “I could build something similar. It would be native, have better OS integration, and be open-source.” So, I did.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*flRG13zcSvVikC6JiJHkUQ.gif" /><figcaption>Capabilities menu</figcaption></figure><p><strong>Why native?</strong></p><p>Atelier seamlessly integrates with your existing apps, including Safari, Finder, Shortcuts, and iWork. Your Mac already has the ability to automate tasks, and Atelier simply provides Claude Code with a seat at the table.</p><h3><strong>What Atelier does differently</strong></h3><p>Claude Desktop is great, but I wanted something that felt like it was designed for macOS, not just ported to it.</p><h4>Conversational UI</h4><p>Atelier lacks “Chat, Cowork, or Code” toggles, consolidating all features into a single session. This is my biggest frustration with Claude Desktop: each tab offers a completely different set of capabilities and operates independently. Forcing users to switch between three tabs for no apparent reason only adds to the frustration, especially considering the app’s sluggish and glitchy performance at the time of writing.</p><h4><em>Automation is built in</em></h4><p>You don’t need to keep the app open. Schedule a task, close it, and then return to the results. Currently, the app mimics the Shortcuts UI to some extent, but I’ve included AppIntents in the roadmap. This will allow you to directly trigger “Ask Claude” (which is currently only available in the iOS app) or automate a project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KjiNILw4rfdAw5VArb25tQ.gif" /><figcaption>Built-in Automations</figcaption></figure><h4><em>Memory is managed automatically</em></h4><p>The app tracks context within a session, so Claude remains sharp without you manually managing it. Now that the context window is 1 million tokens, this is simpler. However, it comes with slightly degraded performance. The app uses hooks to detect the compact window and then times the conversation into reusable pieces for future reference.</p><p>The whole idea of Atelier is to maintain a single, massive conversation, but you’re welcome to create as many as you need.</p><h4><em>Multiple windows, multiple projects</em></h4><p>Open multiple sessions simultaneously, just like you would with your favourite apps. This way, you can switch between tasks without losing your train of thought. Your AI agent should function similarly to your other Mac apps. For example, if you need to work on multiple folders at once, simply open a new window for each folder and chat away.</p><p>You get the idea, a lot of features in the app.</p><h3><strong>Built in 10 days</strong></h3><p>The app is far from perfect, and it’s definitely nowhere near the scope of Claude Desktop. However, it works well, is fast, and is currently available as a free download. Additionally, it’s fully open source, so you can peek into the code or expand its capabilities.</p><h3><strong>What’s next</strong></h3><p>I’m working on deeper OS integrations. The goal is to create an app that can operate autonomously in the background, leveraging macOS’s native scheduling and automation features, allowing you to focus on other tasks.</p><p>If you’re a Mac user residing in Claude Code and have ever wished for a proper home for the CLI, this is it.</p><p>Download Atelier for free → <a href="https://raul.xyz/atelier/">https://raul.xyz/atelier</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lJZCJV0rzcVuqkUQ.png" /><figcaption>SF Symbol logo</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2efb47133da9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Claude Code Canvas, or how I mass-deleted an AppKit project]]></title>
            <link>https://raulriera.medium.com/claude-code-canvas-or-how-i-mass-deleted-an-appkit-project-5b7c81d267c7?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/5b7c81d267c7</guid>
            <category><![CDATA[data-visualization]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[claude-code]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Wed, 25 Feb 2026 16:52:11 GMT</pubDate>
            <atom:updated>2026-02-25T16:52:11.279Z</atom:updated>
            <content:encoded><![CDATA[<p>A few weeks ago, I wrote about <a href="https://raulriera.medium.com/you-can-still-just-do-things-c2ec465e2677.">building something for myself</a> a the premise was straightforward: I wanted something, it didn’t exist, so I built it. This is that story again, except this time I deleted everything halfway through.</p><h3><strong>The</strong> <strong>problem</strong></h3><p>I’ve been using <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> a lot. Across multiple projects, multiple branches, dozens of sessions. It’s awesome; but after a while, I started losing track. Which session was on which branch? What did I ask last Tuesday? What’s still in progress? Claude Code stores all of this locally in JSONL files under <strong>~/.claude</strong>. I wanted something visual. A map of everything I’ve been working on, organized by project and branch, that I could glance at and immediately know where things stand.</p><h4><strong>The</strong> <strong>AppKit</strong> <strong>attempt</strong></h4><p>Naturally, I reached for Swift. It’s what I know best, and a native macOS app felt like the right tool for a local visualization. I started building a radial graph in AppKit. Nodes for projects, branches radiating outward, session cards at the leaves. It looked promising at first, but the more sessions I loaded, the worse it performed.</p><p>Dragging, zooming, rendering — everything got sluggish.</p><p>To clarify, this was entirely my fault. Native code is perfectly capable of handling this. However, while debugging drawing passes and dealing with coordinate spaces, I kept reinvented the wheel. Dealing with bezier curves, hit testing, and pan and zoom gestures; all of which the web has already solved countless times. The JavaScript community is full of examples of precisely these interactive graphs.</p><p>So I did what any reasonable person would do. I selected all, and pressed delete.</p><h3>The pivot</h3><p>Node.js with Express for the backend, vanilla JavaScript and HTML5 Canvas for the frontend. The server reads Claude Code’s local session files, groups them by project and branch, and serves them as JSON. The browser computes a radial layout and draws everything on a Canvas visualizing branches, color-coded projects, interactive session cards you can click to resume directly in Terminal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XTJm9hKiMCmHOz2OP5ujIg.png" /></figure><h3><strong>The</strong> <strong>learning</strong> <strong>side</strong> <strong>quest</strong></h3><p>Every project needs one. Last time it was SwiftUI component models. This time, it was the realization that sometimes the best technical decision is choosing the boring tool that fits the problem, not the sophisticated one you’re most comfortable with.</p><p>I also learned that Claude Code’s local storage format is surprisingly well-structured. Each session gets its own JSONL file with metadata, prompts, and responses.</p><h3><strong>You</strong> <strong>can</strong> <strong>still</strong> <strong>just</strong> <strong>do</strong> <strong>things</strong></h3><p>This is the same lesson from last time. I wanted something. It didn’t exist. So I built it (twice, technically).</p><p>Try it for yourself.</p><p><a href="https://github.com/raulriera/claude-code-canvas">GitHub - raulriera/claude-code-canvas: Visualize your Claude Code sessions as an organic radial mind map</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5b7c81d267c7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[You can still just do things]]></title>
            <link>https://raulriera.medium.com/you-can-still-just-do-things-c2ec465e2677?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/c2ec465e2677</guid>
            <category><![CDATA[motivation]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[workout]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Mon, 03 Nov 2025 15:46:41 GMT</pubDate>
            <atom:updated>2025-11-03T15:46:41.417Z</atom:updated>
            <content:encoded><![CDATA[<h4>The never-ending trope of not finding exactly what I needed led me to build it myself.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BB-QZKn9HcbBg7my74rd8Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SIWj1M0_7cR0ULDhITc0gw.png" /></figure><h3>Workout Widgets App</h3><p>I recently decided to try Apple Fitness+. It’s a beautifully designed app with a wide variety of great workouts. However, despite enjoying the overall experience, I was surprised to find that there were no motivating widgets.</p><p>For me, consistency is built from visibility. It’s about seeing the thing you care about every day, rather than being nudged by another notification you’ll quickly swipe away.</p><p>It all boiled down to one thing: I wanted a widget that would do one job and visually remind me that I haven’t worked out today.</p><p><a href="https://github.com/raulriera/WorkoutWidgetsApp">GitHub - raulriera/WorkoutWidgetsApp: Dead simple workout motivation app. Did you work out today?</a></p><h3>Learning Opportunity</h3><p>As usual, every project requires a new side quest, a small learning opportunity. This time, I repurposed a previous idea into the SwiftUI component model.</p><p>In this case, I took an old concept from an app I worked on a while ago, stripped away the unnecessary layers, and rebuilt it using SwiftUI’s latest features. This wasn’t a requirement, but rather an opportunity to solve the same problem using a new set of tools.</p><h4>Startup Tasks, every app needs them</h4><p>If you’ve worked on apps professionally, you know there’s a set of maintanance or “startup” tasks your app needs to complete before it’s ready for users. This might include selecting your age, your current location, or reading from local storage. I wanted to tackle this problem using SwiftUI component models.</p><p>I tried a few things, but I ended up settling on a custom container. It allowed me to accomplish almost everything I wanted with the cleanest API. However, I’m fully aware that this is over-engineered, especially for the type of app I was making (and the fact that it was only one startup task needed). Nevertheless, it was a fun project to work on, where I could delete everything, try something else, and so on.</p><p>You can see the component <a href="https://github.com/raulriera/WorkoutWidgetsApp/blob/main/WorkoutWidgets/Tasks/TaskContainer.swift">here</a>, and its usage it’s pretty straightforward</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/992/1*4zMgh_AWTXRUQg_Rw9SJoA.png" /><figcaption>TaskContainer example</figcaption></figure><p>TaskContainer is a custom container that iterates over its children and hides anyone whose “task” hasn’t been marked as completed. This could be useful with all the examples above, where you place all your tasks one after the other (or in parallel using a Section group).</p><h3>That’s it</h3><p>This is essentially the entire article and app. I doubt such a simple app would be allowed into the App Store. For now, the code will have to suffice.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c2ec465e2677" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vibing with Copilot]]></title>
            <link>https://raulriera.medium.com/vibing-with-copilot-81a05b50641a?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/81a05b50641a</guid>
            <category><![CDATA[microsoft-copilot]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Tue, 05 Aug 2025 20:20:20 GMT</pubDate>
            <atom:updated>2025-08-05T20:20:20.749Z</atom:updated>
            <content:encoded><![CDATA[<p>There’s no shortage of AI articles out there and yes, this is going to be another one. But I’ve been really enjoying Copilot lately. If you have access to its Agent mode directly within GitHub, it feels a lot like using OpenAI Codex, but with a smoother, more integrated experience.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dKrTQvMm-n982l7i" /><figcaption>Photo by <a href="https://unsplash.com/@solenfeyissa?utm_source=medium&amp;utm_medium=referral">Solen Feyissa</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Vibe coding doesn’t have to be digital slop. It can be just as valuable as a learning tool, a way to bounce around ideas, or simply a way to explore different ways of writing code.</p><p>I recently revived one of my old projects and started using GitHub Copilot’s agent mode to maintain it. In just two days, I’ve shipped more features and improvements than I had in the last six years — mostly because I just haven’t had the time. Copilot helps me kick off tasks quickly, and I either merge the suggestions as-is or make small tweaks before merging.</p><p>It’s genuinely been a magical experience ✨.</p><iframe src="https://cdn.embedly.com/widgets/media.html?type=text%2Fhtml&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;schema=twitter&amp;url=https%3A//x.com/raulriera/status/1952542195531018639&amp;image=" width="500" height="281" frameborder="0" scrolling="no"><a href="https://medium.com/media/0684a5c0f77e668e0fd55cd31ab38df2/href">https://medium.com/media/0684a5c0f77e668e0fd55cd31ab38df2/href</a></iframe><p>AI might not be for everyone. But one thing is clear: we are the real winners of the AI race. Every company is building a similar product, all racing to become the next big thing in AI. The result is that everything is becoming better, faster, cheaper, and more innovative. It has genuinely never been a more exciting time to be a developer.</p><p>For now, I’ll keep experimenting with all the tools out there. But I’ve got to hand it to Microsoft — while so many of us are talking about coding in Cursor, VSCode and Copilot are steadily carving out a solid place in my development workflow.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81a05b50641a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Remove that blue color from your React Native applications]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://raulriera.medium.com/remove-that-blue-color-from-your-react-native-applications-7964fd0e87a3?source=rss-8501090bb2de------2"><img src="https://cdn-images-1.medium.com/max/888/1*U0A7DF8Hrqjjsv2kzeHAUA.gif" width="888"></a></p><p class="medium-feed-snippet">While using React Native, don&#x2019;t forget about the native part. Remember to theme the native views with your custom colours.</p><p class="medium-feed-link"><a href="https://raulriera.medium.com/remove-that-blue-color-from-your-react-native-applications-7964fd0e87a3?source=rss-8501090bb2de------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://raulriera.medium.com/remove-that-blue-color-from-your-react-native-applications-7964fd0e87a3?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/7964fd0e87a3</guid>
            <category><![CDATA[react-native-modules]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Sat, 21 Aug 2021 17:00:37 GMT</pubDate>
            <atom:updated>2021-08-22T18:53:35.783Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Creating a GitHub Action]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-link"><a href="https://raulriera.medium.com/creating-a-github-action-aeff73ddd151?source=rss-8501090bb2de------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://raulriera.medium.com/creating-a-github-action-aeff73ddd151?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/aeff73ddd151</guid>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[project-management]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Mon, 03 May 2021 02:47:08 GMT</pubDate>
            <atom:updated>2021-05-03T02:47:08.724Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Joyful animations using arcs]]></title>
            <link>https://raulriera.medium.com/smoothanimations-bf063b912430?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf063b912430</guid>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[emoji]]></category>
            <category><![CDATA[animation]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Fri, 19 Jun 2020 02:34:49 GMT</pubDate>
            <atom:updated>2020-06-20T03:23:09.628Z</atom:updated>
            <cc:license>http://creativecommons.org/publicdomain/zero/1.0/</cc:license>
            <content:encoded><![CDATA[<h4>From tweet to polished animation</h4><p>The following tweet inspired me to finish an animation I had planned for one of my apps. The end result was better than I expected.</p><h3></h3><p></p><p>In <a href="https://itunes.apple.com/app/emoji-stickers-pack/id1131713856">Emoji Stickers</a>, every time you select an emoji they fly into your canvas. This animation was just a straight line from point A to point B. There was nothing wrong with it, but always felt kind of stiff. Using curves, we can do better.</p><h4>The code</h4><p>I knew what I needed to do, I remember watching a WWDC video a while ago about CAKeyframeAnimation and using paths to animate along a given area. I was surprised that the implementation was actually very simple.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hM0ZvCl6A-zMsVzmPKCVhQ.png" /><figcaption>Tiny example</figcaption></figure><p>That is literally all, of course you need to tweak your timing functions, duration, etc to really polish it. But I will ignore that for this article and focus on the challenging bit, that second line. How can I draw this line? And more importantly, how can I debug it?</p><h4>Drawing the path</h4><p>I knew I wanted to add a curve into the translation of the view, changing the view origin wasn’t going to be enough anymore. Enter UIBezierPath and the delightful addQuadCurve function to literally do just want we need.</p><p>The final implementation looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*48NFuCTHhrxwCQVznlVfKA.png" /><figcaption>The animation properties are omitted for simplicity, you will find the full source on GitHub</figcaption></figure><p>If we breakdown the previous code snippet, you will find two (2) main themes: finding the points, and drawing a small curve between</p><h4>Finding the origin and final destination of the curve.</h4><p>Knowing the two points: the origin being the starting position of the emoji, and the destination the exact centre of the canvas. Now, all I needed to do is create a CGRect between the two points (this little rectangle will come handy in the next step)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ry0wv0zRp36OddnrZeyB-A.png" /><figcaption>CGRect extension to draw a rectangle between 2 points</figcaption></figure><p>With this information, the next step is to draw the line.</p><h4>Plotting a small curve between the points</h4><p>Drawing a curve between the two positions requires a control point which apple describes as follows:</p><blockquote>The control point of the curve.</blockquote><p>Not great 🙃, thankfully they have a nice illustration that is more helpful.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*pEmHv7akUWJzpjbLvKfl2A.jpeg" /><figcaption>Source: <a href="https://developer.apple.com/documentation/uikit/uibezierpath/1624351-addquadcurve">Apple documentation</a></figcaption></figure><p>We find such point using our previous rectangle:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UMDgyJMmu0kPRcMwqmTVtg.png" /><figcaption>Random control point</figcaption></figure><p>By randomly choosing between the bottom and top of the rectangle and assign that as the Y coordinate, and then choosing the middle of the rectangle as the X coordinate. We create a small amount of playfulness to the animation by giving at least two (2) variants.</p><h4>Debugging the path</h4><p>This was all great in paper, but how can we debug the rectangles, lines, and curves we are drawing? We probably have multiple choices, but I went with the most simple ones I could think of: using the debugger with quick look, and drawing them out to the app for better visualization.</p><p>Using the debugger was the easy part, we need to put a breakpoint in place right after we define our path and once the runtime stops there, simply click on it to see more information.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*0uLE4nTL9b2_aM7-40SMLw.gif" /><figcaption>Debugging using QuickLook</figcaption></figure><p>The most difficult but totally <a href="https://twitter.com/raulriera/status/1272180095701188613">“tweetable”</a> solution, was to draw the paths on screen every time we add something. That can be achieved with the following code snippet:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aPooWqcsJp9MmJi4t0-4lg.png" /><figcaption>Debugging by drawing on screen</figcaption></figure><p>Technically, all of them could be CAShapeLayers but I started with a UIView for some reason 😅. As you can see, we create a view representation of the rectangle between the two points, and finally add a layer to the canvas with the shape of the path we constructed.</p><h4>Seeing it all together</h4><p>That is all, and the best part is how it looks! This was probably one of the quickest wins I had in this project while still having a great impact.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*WVK13ZQ0AaABSA9SFh9xkA.gif" /></figure><h4>Further reading</h4><p>That is all!, as always you can find the full source code on GitHub <a href="https://github.com/raulriera/technical-articles">https://github.com/raulriera/technical-articles</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf063b912430" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[UserInterfaceLevel, the future of floating apps]]></title>
            <link>https://blog.devgenius.io/userinterfacelevel-the-future-of-floating-apps-bec2d3328e79?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/bec2d3328e79</guid>
            <category><![CDATA[user-interface]]></category>
            <category><![CDATA[uitraitcollection]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Sat, 06 Jun 2020 16:23:14 GMT</pubDate>
            <atom:updated>2020-06-20T03:19:15.676Z</atom:updated>
            <cc:license>http://creativecommons.org/publicdomain/zero/1.0/</cc:license>
            <content:encoded><![CDATA[<h3>UserInterfaceLevel, the future of floating apps?</h3><h4>iOS 13 brings new dynamism to your apps.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MkMlRltDlURkncsR" /><figcaption>Photo by <a href="https://unsplash.com/@pemmax?utm_source=medium&amp;utm_medium=referral">Przemyslaw Marczynski</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Last year at Shopify we started developing the <a href="https://www.shopify.com/pos">All-new Point of Sale</a>. There was a small problem, given that all screens are presented full screen to the user we needed the ability to distinguish a modal screen versus the rest. iOS 13 had a great answer for this.</p><p>It feels like every new iOS version adds something to UITraitCollection or UIUserActivity. iOS 13 was no different, there was a small but powerful addition to UITraitCollection which comes handy when developing your universal apps. Specially if your app is presented as a floating window, that addition was userInterfaceLevel¹.</p><h4>What is UserInterfaceLevel?</h4><p>Apple describes it as the visual level for content in a window. The possible values are base, elevated, and unspecified. The first one being the window’s main content and the last one anything above it*. This will be the perfect match for our need of modal windows having a dedicated background colour.</p><blockquote>* Check the comment section for a great explaining from <a href="https://medium.com/u/4a59fa99a5c4">Geoff Hackworth</a> about how these values changes depending on other factors</blockquote><h4>Using it to meet our requirement</h4><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*e29n9d7QSoBrTpVhcV892A.png" /><figcaption>AdaptiveColor source code</figcaption></figure><p>The previous snippet is how Shopify’s <a href="https://shopify.com/pos">Point of Sale application</a> is handling dynamic colours. You should focus on line #24, we detect the current elevation of the user interface and decide which of the two colour sets to use for this particular colour.</p><p>Now, let’s say we want to change the background colour of a view all we need to do is:</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*4ArYjxWzHNyyEPRU4PSEiA.png" /><figcaption>Example usage of AdaptiveColor</figcaption></figure><p>And thanks to the excellent UIAppearance² we can style our UINavigationController similarly how we styled the background view, and all our screens will be displayed with the correct colour.</p><p>Putting everything together into a project, it looks something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*VcQWI-ZVnBkAVBeS39tsnA.gif" /><figcaption>Changes in the background colour reacting to presentation levels</figcaption></figure><h4>Further reading</h4><p>That is all!, as always you can find the full source code on GitHub</p><p><a href="https://github.com/raulriera/technical-articles">raulriera/technical-articles</a></p><ol><li>Apple documentation <a href="https://developer.apple.com/documentation/uikit/uitraitcollection/3238085-userinterfacelevel">https://developer.apple.com/documentation/uikit/uitraitcollection/3238085-userinterfacelevel</a></li><li>Apple documentation <a href="https://developer.apple.com/documentation/uikit/uiappearance">https://developer.apple.com/documentation/uikit/uiappearance</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bec2d3328e79" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/userinterfacelevel-the-future-of-floating-apps-bec2d3328e79">UserInterfaceLevel, the future of floating apps</a> was originally published in <a href="https://blog.devgenius.io">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Interface Builder and Code ‍♂️✨]]></title>
            <link>https://raulriera.medium.com/using-interface-builder-and-code-%EF%B8%8F-d9db30269d1d?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/d9db30269d1d</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[user-interface]]></category>
            <category><![CDATA[interfaces]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Sun, 05 May 2019 16:20:17 GMT</pubDate>
            <atom:updated>2019-05-05T16:25:15.940Z</atom:updated>
            <cc:license>http://creativecommons.org/publicdomain/zero/1.0/</cc:license>
            <content:encoded><![CDATA[<h3>FunctionalTableData and Interface Builder 🎨✨</h3><h4>Interface Builder is amazing for building UI. Code is great for extensibility. Why not use both?</h4><p>I have a long-running joke in my <a href="https://twitter.com/raulriera/">Twitter bio</a> about fighting in the great Storyboards vs Code wars. Using things like Storyboards is a hot topic among iOS developers. There have been many before it:</p><ul><li>Automatic Reference Counting vs Manual Memory Management.</li><li>Auto Layout vs Manual Layout.</li><li>Swift vs Objective-C.</li></ul><p>You get the idea, status-quo versus new. I like storyboards, they allow me to create complex views very fast. But, using them comes at a great “merge conflict” cost if you are working with more than yourself.</p><h3>What can we do about it?</h3><p>I have praised <em>FunctionalTableData</em> before, a declarative UI building library developed at Shopify. Newcomers to this library will find how verbose it is to create a Cell (UIView subclass, and a State) when compared with similar solutions like React Components.</p><p>We can do better by using code for the states, and making the views using Interface Builder. The best of the two worlds.</p><h3>Putting this crazy idea into practice</h3><p>We won’t cover how to use <em>FunctionalTableData,</em> we did that in <a href="https://medium.com/@raulriera/building-apps-with-functionaltabledata-c99bfaa7e2e5">Building Apps with FunctionalTableData.</a> We are going to skip forward and focus on the views. For that, we are going to turn to Xcode’s Interface Builder and create a new <em>.xib</em> file.</p><p>Using everyone’s favourite app as a guideline, lets recreate Instagram’s profile header. At the moment of this writing it looks like:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vuqLK5uEzM08lqCTqD_H1g.jpeg" /><figcaption>Profile header from Instagram (Image 1)</figcaption></figure><p>Turning to Interface Builder, we are going to add UIStackViews, UILabels, UIImageView, and an UIButton. After dragging around a bunch of views, it looks like so:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BYyMQ4pcSCC1AfIKVhH1Jg.png" /><figcaption>Finished version of our own Instagram header view (Image 2)</figcaption></figure><p>Imagine doing all those stack views and views by code, I am screaming too. But, how do we get this view to work with our <em>HostCell</em> implementation?</p><h3>Loading the main view from a .xib file</h3><p>Even though we created everything using Interface Builder, we still need to write a bit of code for our header file. Every <em>IBOutlet</em> connecting the views that we will manage with the state, which we will build later.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HSqpoI0os70DXly7YR2xUA.png" /><figcaption>Our view (Image 3)</figcaption></figure><p>Everything in here looks very similar many apps we have done before, but what is that <em>loadNib</em> method? Without it, we will have to load the UINib from a Bundle, instantiate the view, and then apply constraints to pin it to the edges. Or, we can write a simple protocol to do all of that for us:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WEqdCpe6ihnn7j06Jhq39A.png" /><figcaption>Protocol (Image 4)</figcaption></figure><p>This protocol is very straightforward, the best thing it does is matching the name of the current class to our .xib file. That way, if we use it in our InstagramHeaderView.swift (See Image 3), we need its corresponding .xib file to be named InstagramHeaderView.xib.</p><p>No Cell in <em>FunctionalTableData</em> is complete without a state, let’s quickly create it using the knowledge we already have. If we have previously gone over the trouble of creating small state files for the base iOS views (UIButton, UILabel, etc) using them for big states like this one become as simple as creating properties.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K5SQv1ENpl1UB8V03rjXTA.png" /><figcaption>State (Image 5)</figcaption></figure><p>Noticed how instead of creating multiple properties to manage everything about a Button or an Image, we simply create a property that holds a ButtonState and an ImageState. To learn more about these states, take a look at FunctionalTableData’s <a href="https://github.com/Shopify/FunctionalTableData/tree/master/FunctionalTableDataDemo/Cells">example project</a>.</p><h3>Putting it all together</h3><p>You know the drill by now, we normally create a typealias to hide all the implementation details required by HostCell. Our new cell would be something like this</p><pre>typealias <strong>InstagramHeaderCell</strong> = HostCell&lt;<strong>InstagramHeaderView</strong>, <strong>InstagramHeaderState</strong>, LayoutMarginsTableItemLayout&gt;</pre><p>That is pretty much it! ✨. Using this cell is something we have cover before, if you need a refresher please head over to <a href="https://medium.com/@raulriera/building-apps-with-functionaltabledata-c99bfaa7e2e5">Building Apps with FunctionalTableData</a>.</p><p>Did I miss anything? Get in touch on Twitter at <a href="https://twitter.com/raulriera">@raulriera</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d9db30269d1d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Undo and Redo support to iOS apps]]></title>
            <link>https://raulriera.medium.com/undo-and-redo-support-to-ios-apps-4c9d7afea6a2?source=rss-8501090bb2de------2</link>
            <guid isPermaLink="false">https://medium.com/p/4c9d7afea6a2</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swift-programming]]></category>
            <category><![CDATA[user-experience]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[app-development]]></category>
            <dc:creator><![CDATA[Raul Riera]]></dc:creator>
            <pubDate>Sun, 27 Jan 2019 19:31:00 GMT</pubDate>
            <atom:updated>2019-01-27T21:26:26.101Z</atom:updated>
            <content:encoded><![CDATA[<h3>Adding Undo and Redo support to iOS</h3><h4>People make mistakes. Let’s use allow undoing.</h4><p>You have accidentally shaken your phone and noticed that little alert screen that says “Undo [something]”. In this story we are going to implement Undo and Redo actions in an iOS app.</p><p>By now you are making all your screens using a declarative and functional approach, right? 😉 If not, <a href="https://medium.com/@raulriera/building-apps-with-functionaltabledata-c99bfaa7e2e5">you can read all about it</a>. Expanding on that approach, we can easily implement undo actions into our app if all our View Controller state is encapsulated like it was demostrated in that article.</p><h4>Looking at the documentation</h4><p>When I looked at <a href="https://developer.apple.com/documentation/foundation/undomanager">Undo Manager</a> it appeared like I was going to be dealing with Selectors, old Objective-C API, and whatever else was lurking underneath. I tried to get around this by creating a wrapper struct with some syntactic sugar.</p><pre>struct Undoer {<br>  let undoManager: UndoManager<br>  ...<br>}</pre><p>Thankfully, <a href="https://medium.com/u/b52ce6710722">Geoffrey Foster</a> talked me out of it and I end up choosing a better approach. By simply extending UndoManager to include one more function. Now, taking everything I had in the previous wrapper, all I was left with was this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T5LLjgfZ4nroHj1qT07lTw.png" /><figcaption>Pretty simple right?</figcaption></figure><p>Pretty simple right? To be honest, the biggest issue with writing this short function was embracing the fact that you want to capture your variables inside the registerUndo closure, while also having it call itself.</p><h4>Exploring the code</h4><p><a href="https://developer.apple.com/documentation/foundation/undomanager">UndoManager</a> works exactly like that. It retains a copy of the data in the closure so you can revert any changes by calling undoManager.undo() or redo() for that matter. Doing so, executes our handler callback and recursively calls itself again, but this time with the values inverted. Creating that loop of undo and redo actions that we desire.</p><h4>Fixing the bug 🙃</h4><p>There is one issue that you probably spotted by now. If we use reference types, we won’t be maintaining the previous data. Thankfully that is why we have the Codable constraint in the generic type T.</p><p>By leveraging Codable, we can implement a quick and dirty version of copy to serialize and deserialze the content of the data, so we can maintain the state.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_HfcaJ7OXOrsrWDbRa2iEA.png" /><figcaption>Don’t @ me 🙈</figcaption></figure><p>This is more like it, now our UndoManager can store and restore the state of any class or struct, and we barely even had to break a sweat writing this.</p><p>You can find the source code of this function with a quick implementation into a View Controller in the following link.</p><p><a href="https://github.com/raulriera/technical-articles/tree/master/Adding-Undo-and-Redo%20support-to-iOS">raulriera/technical-articles</a></p><p>Did I miss anything? Get in touch on Twitter: <a href="https://twitter.com/raulriera">@raulriera</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c9d7afea6a2" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>