Build a URL Shortener Flutter App with Flet Python Framework | by Henri Ndonko | Dec, 2022

Build cross-platform Flutter app with Python

photo by steve johnson Feather unsplash

In my previous article, we saw how to build a Markdown editor Flutter app with Fleet.

Today we’ll be using Flet to create something a little different and useful. A URL/link shortener application. Scroll down till the end of this article to check the final result. ,

For this project we will need only two python packages: fleet And pieshorters,

Flet will be the person in charge of building and rendering the UI, while Pyshorteners will be the backend person for shortening the given URL/link.

From this, you can already understand that Flet can be combined with any Python library of your choice (in our case pyshorteners).

please make sure you have Python (preferably v3.7 or above) is installed, then run these two commands in your terminal/command line:

pip install flet
pip install pyshorteners

I suggest you do it in a Virtual Machine (VM).

Once the installation is done, create a new file and name it whatever you want (ex: my-url-shortener) and it will replace the original “Hello, World!” Code using your favorite IDE to make sure you are good to go.

import flet as ft

def main(page: ft.Page):
page.add(ft.Text(value="Hello, world!"))

ft.app(target=main)

Flat Hello World App - Dark Mode
hello world – dark mode
Flet Hello World App - Lite Mode
hello world – lite mode

Throughout this article, I will be importing Flet with the alias ftJust like Numpy is usually aliased np or panda pd,

Execution of that code block opens a parent window containing the rendered output. Since we’ll be dealing with links, let’s render the output in our web browser. To do this, modify the last line of code as shown below:

ft.app(target=main, view=ft.WEB_BROWSER)  # add 'port' parameter to specify the port to be used
Flat hello world in browser - dark mode
Hello world in browser – dark mode
Flat hello world in browser - lite mode
Hello world in browser – lite mode

The UI for this project will be straightforward. To receive user input (url/link) we will need a text field with a button to validate that input.
This input will be sent to the backend for processing, and the output will be displayed as text on the screen.

We will have one button to copy the generated shortened link and another to open/view the link in a browser tab. Exciting, isn’t it?

Let’s give our application a title and add an App Bar.

import flet as ft

def main(page: ft.Page):
page.title = "URL Shortener" # title of application/page
page.horizontal_alignment = "center" # center our page's content (remove or change at wish)

page.appbar = ft.AppBar(
title=ft.Text("URL Shortener", color=ft.colors.WHITE), # title of the AppBar, with a white color
center_title=True, # we center the title
bgcolor=ft.colors.BLUE, # a color for the AppBar's background
)

page.add(ft.Text(value="Hello, world!")) # some placeholder content (nothing will be shown without this line)

ft.app(target=main, view=ft.WEB_BROWSER) # add 'port' parameter to specify the port to be used

Title and Appbar - Hello world in browser with dark mode
Title and Appbar – Hello world in browser with dark mode
title and appbar - hello world in browser with lite mode
title and appbar – hello world in browser with lite mode

After executing your program, you should see something similar to the one in the above images.

‘one of the images’ because Flet uses your system’s theme by default, For consistency’s sake, let’s use the light theme. So, let’s clearly set theme_mode,

#...
def main(page: ft.Page):
page.theme_mode = "light" # there are only 3 possible values: "dark", "light" and "system"
#...

I omit some code lines (using #…) to save some space.

I mentioned earlier that we will be using text fields for this.

Let’s create one, store it in a variable named text_fieldand add it to our page/UI.

    # ...
page.appbar = ft.AppBar(
# ...
)

text_field = ft.TextField(
value=' # a test link
label="Long URL", # the field's label
hint_text="type long url here", # the field's hint-text
max_length=200, # the maximum length of inputted links
keyboard_type="url", # the field's keyboard type
suffix=ft.FilledButton("Shorten!"), # a button in the field, to shorten the inputted links
)

page.add(
text_field,
ft.Text("Generated URLs:", weight="bold", size=23)
) # add our text field to the page/UI

# ...

Now after your program executes, you should see something similar to this:

textfield for storing user input

Before moving on, let’s import pyshorteners under Flet and initialize it.

import flet as ft
import pyshorteners # pip install pyshorteners

shortener = pyshorteners.Shortener() # create an instance (initialization)
# ...

Now, while shortening the long URL entered, we will display a Row Consisting of three main things: a shortened link, a copy button, and a button to open the shortened link in a browser tab.

This Row Will be displayed multiple times, so we need to create a separate and reusable component. We will create a python class and put it below shortener Char.

# ...

class ShortLinkRow(ft.Row):
# a row containing the shortened url, and two buttons ('copy', and 'open in browser')

def __init__(self, shortened_link, link_source):
"""
We create a new class called `ShortenedLinkRow` that inherits from `ft.Row`.
The constructor takes two arguments/parameters: `shortened_link` and `source`.

:param shortened_link: the shortened link
:param link_source: the service hosting the shortened_link
"""
super().__init__() # required when overwriting the constructor

self.tooltip = link_source # set the tooltip of the row itself to the link provider/source
self.alignment = "center" # center the contents of this row

# the controls/content of our Row
self.controls = [
ft.Text(value=shortened_link, size=16, selectable=True, italic=True),
ft.IconButton(
icon=ft.icons.COPY, # the icon to be showed
on_click=lambda e: self.copy(shortened_link), # when this button is clicked, call the `copy` method, passing the shortened link as parameter
bgcolor=ft.colors.BLUE_700,
tooltip="copy" # to be showed when hovering on this button
),
ft.IconButton(
icon=ft.icons.OPEN_IN_BROWSER_OUTLINED, # the icon to be showed
tooltip="open in browser", # to be showed when hovering on this button
on_click=lambda e: e.page.launch_url(shortened_link) # when this button is clicked, open a browser tab with that shortened link
)
]

def copy(self, value):
"""
It copies the given value to the clipboard, and opens a Snackbar to inform the user.
:param value: The value to be copied to the clipboard
"""
self.page.set_clipboard(value)
self.page.show_snack_bar(
ft.SnackBar(
ft.Text("Link copied to clipboard!"),
open=True
)
)

Having done this, now we need to listen for events in the textfield so that we can show the output at the right time.

We will listen for the click of the ‘Submit’ button when the text field is in focus and the ‘Enter’ keyboard key is pressed. When one of these events occurs, a special task named Flet will run. shortenWhich we will make in a while.

modify yours below text_field variables:

text_field = ft.TextField(
# ...
suffix=ft.FilledButton("Shorten!", on_click=shorten), # the function to be called when this button will be clicked
on_submit=shorten # the function to be called once the user presses the Enter keyboard key to submit entry
)

Now let’s create a callback function, and add it to the main function.

# ...(below page.appbar assignment)

def shorten(e):
"""Grabs the URL in the textfield, and displays shortened versions of it."""

user_link = text_field.value # retrieve the content of the textfield

if user_link: # if the textfield is not empty
# if the entered text in the textfield is not a valid URl, the program may break, hence the need to catch that
try:
page.add(ft.Text(f"Long URL: user_link", italic=False, weight='bold'))
page.add(ShortLinkRow(shortened_link=shortener.tinyurl.short(user_link), link_source="By tinyurl.com"))
page.add(ShortLinkRow(shortened_link=shortener.chilpit.short(user_link), link_source="By chilp.it"))
page.add(ShortLinkRow(shortened_link=shortener.clckru.short(user_link), link_source="By clck.ru"))
page.add(ShortLinkRow(shortened_link=shortener.dagd.short(user_link), link_source="By da.dg"))

except Exception as exception: # the error might be that a url shortening service from pyshorteners failed to shorten our url
print(exception)
# inform the user that an error has occurred
page.show_snack_bar(
ft.SnackBar(
ft.Text("Sorry, but an error occurred. Please retry, or refresh the page."),
open=True
)
)

else: # if the textfield is empty (no text)
# inform the user
page.show_snack_bar(
ft.SnackBar(
ft.Text("Please enter a URL in the field!"),
open=True
)
)
# ...

If you are lost in line, please check this gist for the entire code, Below is a capture of the final result:

I have deployed an online version of this app Here for you. Test it and please give me your impressions.

Note that you can eventually package this app as a standalone executable file either deploy it on the web, This is just a cross-platform version of Flet.

To make this project better or more advanced try this:

you can use This As a reference/workaround if you get stuck. Please, let me know if you tried it or have any questions. I’d be happy to help.

Thanks for reading!

Leave a Reply