Skip to content

Commit

Permalink
Merge pull request #4 from redromnon/testing
Browse files Browse the repository at this point in the history
Prepare v2
  • Loading branch information
redromnon authored May 12, 2024
2 parents aea380e + 5426692 commit afe9779
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 268 deletions.
75 changes: 0 additions & 75 deletions src/libutilities.py

This file was deleted.

10 changes: 8 additions & 2 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ def main(page: ft.Page):

page.title = "iBackep"
page.vertical_alignment = "center"
page.theme_mode = "system"
page.theme_mode = "dark"

#Pass version to about
get_version(version)

#App title and version
app_name = ft.Row([ft.Text("iBackep", size = 56, weight="bold")], alignment="center")
app_name = ft.Row(
[
ft.Text("iBackep", size = 56, weight="bold", color=ft.colors.WHITE),
ft.Text(version, size = 20, weight=ft.FontWeight.NORMAL, color=ft.colors.WHITE)
],
alignment=ft.MainAxisAlignment.CENTER,
)
page.add(app_name)

ibackep = App()
Expand Down
12 changes: 7 additions & 5 deletions src/ui/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ def build(self):


self.about_icon = ft.IconButton(icon=ft.icons.QUESTION_MARK_ROUNDED, icon_size=18,
tooltip="About", on_click=self.display_about)
tooltip="About", on_click=self.display_about, icon_color=ft.colors.WHITE70
)

self.about_modal = ft.AlertDialog(title=ft.Text("About", text_align="center"),
content=ft.Column(
[
ft.Text(self.desc, text_align="center", style="bodySmall", size=14),
ft.TextButton("Website", on_click=lambda e: wb.open("https://github.com/redromnon/iBackep"))
], horizontal_alignment="center", height=120
)
ft.Text(self.desc, text_align="center", theme_style="bodySmall", size=14),
], horizontal_alignment="center", height=120,
),
actions_alignment="center",
actions=[ft.TextButton("Website", on_click=lambda e: wb.open("https://github.com/redromnon/iBackep")),]
)

return ft.Stack([self.about_modal, self.about_icon])
Expand Down
136 changes: 65 additions & 71 deletions src/ui/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import flet as ft
from libutilities import scan
import flet as ft, traceback
from ui.about import About
from ui.encrypt import Encrypt
from ui.operations import Operation
import pymobiledevice3.lockdown, pymobiledevice3.exceptions, pymobiledevice3.services.mobilebackup2

class App(ft.UserControl):

Expand All @@ -23,39 +23,39 @@ def build(self):
self.no_device_dialog = ft.SnackBar(content=ft.Text("No device found"))

self.no_folder_selected_dlg = ft.SnackBar(content=ft.Text("Please select a destination folder using the folder icon"))


#Banner dialog
self.lib_not_installed_banner = ft.Banner(
content=ft.Text("Looks like libimobiledevice or libimobiledevice-utils is not installed"),
actions=[ft.TextButton("Ok", on_click=self.close_banner)]
)

self.error_message_dlg = ft.SnackBar(content=None)

#Folder
self.folder_picker = ft.FilePicker(on_result=self.folder_dialog_result)

self.display_folderpath = ft.TextField(
hint_text="Select folder icon", width=400, read_only=True, border="none",
filled=True, max_lines=3, color="#a6a6a6"
filled=True, max_lines=3, color=ft.colors.WHITE70
)

self.select_folder_icon = ft.IconButton(
icon=ft.icons.FOLDER_ROUNDED, tooltip="Select folder location",
icon_size=36, on_click=lambda e: self.folder_picker.get_directory_path()
icon_size=36, on_click=lambda e: self.folder_picker.get_directory_path(),
icon_color=ft.colors.WHITE70
)


#Options
self.backupbtn = ft.ElevatedButton(
"Backup", icon=ft.icons.SETTINGS_BACKUP_RESTORE_ROUNDED, on_click=self.do_backup,
disabled=False
"Backup", icon=ft.icons.SETTINGS_BACKUP_RESTORE_ROUNDED,
on_click=lambda e: self.call_operations(backup=True),
disabled=False, style=ft.ButtonStyle(shape=ft.StadiumBorder(), padding=15),
icon_color=ft.colors.BLACK87, color=ft.colors.BLACK87, bgcolor=ft.colors.WHITE
)

self.restorebtn = ft.ElevatedButton(
"Restore", icon=ft.icons.RESTORE_ROUNDED, on_click=self.do_restore,
disabled=False
)
"Restore",
icon=ft.icons.RESTORE_ROUNDED,
on_click=lambda e: self.call_operations(restore=True),
disabled=False, style=ft.ButtonStyle(shape=ft.StadiumBorder(), padding=15),
icon_color=ft.colors.BLACK87, color=ft.colors.BLACK87, bgcolor=ft.colors.WHITE
)



Expand All @@ -73,8 +73,7 @@ def build(self):
self.main_container = ft.Stack(
[
#Alerts and dialogs go here
self.lib_not_installed_banner, self.operation_dialog,
self.no_device_dialog, self.no_folder_selected_dlg,
self.operation_dialog, self.no_device_dialog, self.no_folder_selected_dlg, self.error_message_dlg,

#Others
ft.Column(
Expand All @@ -96,77 +95,72 @@ def folder_dialog_result(self, e: ft.FilePickerResultEvent):

self.update()


#Close action finished banner
def close_banner(self, e):

if(self.lib_not_installed_banner.open):
self.lib_not_installed_banner.open = False

self.update()


#Call backup/restore/cancel actions
def do_backup(self, e):
#Call backup/restore/cancel actions
def call_operations(self, backup=False, restore=False):

#check if folder path is specified
#check if folder path is specified and run operation
if(len(self.display_folderpath.value) == 0):

self.no_folder_selected_dlg.open = True
self.update()

return


#check if lib is installed & device is connected
lib_installed, status = scan()

if lib_installed and status:
print("Device found!")

#Run backup operation
print("Backup running...")
pwd = self.pwd_encrypt.get_pwd()#Check if password is given
self.operation_dialog.backup(self.display_folderpath.value, pwd)

elif lib_installed and not status:
#Disable buttons
self.backupbtn.disabled = True
self.restorebtn.disabled = True
self.update()

#to connect to device via USB and perform operations
try:
#Create lockdown client
lockdown_client = pymobiledevice3.lockdown.create_using_usbmux()
print(lockdown_client.display_name)
#handle exception where device is not available
except pymobiledevice3.exceptions.ConnectionFailedToUsbmuxdError:
print(traceback.format_exc())
self.no_device_dialog.open = True
self.update()

#run operations if lockdown client creation is successful
else:
self.lib_not_installed_banner.open = True
#Create backup/restore service
service = pymobiledevice3.services.mobilebackup2.Mobilebackup2Service(lockdown=lockdown_client)

self.update()
#Check if password is given
pwd = self.pwd_encrypt.get_pwd()

backup_exists = self.operation_dialog.check_if_backup_exists(self.display_folderpath.value)
print('New backup folder?:', backup_exists)

def do_restore(self, e):

#check if folder path is specified
if(len(self.display_folderpath.value) == 0):

self.no_folder_selected_dlg.open = True
self.update()
if backup:
#Run backup operation
print("Backup running...")
status = self.operation_dialog.backup(self.display_folderpath.value, pwd, service, backup_exists)

return

if status is False:
self.error_message_dlg.content = ft.Text("Backup failed")
self.error_message_dlg.open = True

#check if lib is installed & device is connected
lib_installed, status = scan()
self.update()

if lib_installed and status:
print("Device found!")
if restore:
#Run restore operation
print("Restore running...")
status = self.operation_dialog.restore(self.display_folderpath.value, pwd, service, lockdown_client.identifier)

#Run restore operation
print("Restore running...")
pwd = self.pwd_encrypt.get_pwd()#Check if password is given
self.operation_dialog.restore(self.display_folderpath.value, pwd)
if status is False:
self.error_message_dlg.content = ft.Text("Restore failed: Enter correct password for the encrypted backup")
self.error_message_dlg.open = True

elif lib_installed and not status:
self.no_device_dialog.open = True
self.update()

else:
self.lib_not_installed_banner.open = True

self.update()
self.update()

lockdown_client = None
service = None
backup_service = None
pwd = None

#Renable buttons
self.backupbtn.disabled = False
self.restorebtn.disabled = False
self.update()
46 changes: 13 additions & 33 deletions src/ui/encrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,37 @@ class Encrypt(ft.UserControl):

def build(self):

self.encrypt_checkbox = ft.Checkbox(
fill_color={ft.MaterialState.HOVERED: ft.colors.LIGHT_BLUE}, on_change=self.enable_checkbox,
tooltip="Enable encryption"
)

self.password_field = ft.TextField(
password=True, can_reveal_password=True, disabled=True, width=270, height=40,
content_padding=ft.padding.only(bottom=15, left=10), hint_text="Encryption password"
password=True, can_reveal_password=True,
filled=False, border=ft.InputBorder.UNDERLINE,
hint_text="Encryption password"
)

self.info_button = ft.IconButton(
icon=ft.icons.INFO_ROUNDED, icon_size=28, on_click=self.toggle_help, tooltip="Show encryption help"
icon=ft.icons.INFO_ROUNDED, icon_size=28, on_click=self.toggle_help, tooltip="Show encryption help",
icon_color=ft.colors.WHITE70
)

self.encrypt_help = ft.AlertDialog(
title=ft.Text("Encryption Help", text_align="center"),
content=ft.Column(
[
ft.Text("Your backup can be protected by encrypting it with a password. Just enable the checkbox and type your password.\n\n" +
"When performing a BACKUP, you need to set a password and encrypt it for the first time only." +
" There's no need to insert the password every time once it's already encrypted.\n\n" +
"When performing a RESTORE however, you will need to insert the password every single time.",
text_align="center", style="bodySmall", size=14),
ft.Text("You are required to enter the correct password if the backup is encrypted.",
text_align="center", theme_style="bodySmall", size=13),
],
horizontal_alignment="center", height=150, width=500
horizontal_alignment="center", height=50, width=200
),
actions=[ft.TextButton("Ok", on_click=self.toggle_help)], modal=True
actions=[ft.TextButton("Ok", on_click=self.toggle_help)], modal=True,
actions_alignment=ft.MainAxisAlignment.CENTER
)

return ft.Row([self.encrypt_checkbox, self.password_field, self.info_button, self.encrypt_help], spacing=10, alignment="center")
return ft.Row([self.password_field, self.info_button, self.encrypt_help], spacing=10, alignment="center")


def enable_checkbox(self,e):

if self.encrypt_checkbox.value:

self.password_field.disabled=False
self.update()

else:

self.password_field.disabled=True
self.update()

def get_pwd(self):

if self.encrypt_checkbox.value:

if len(self.password_field.value) > 0:

return self.password_field.value
return self.password_field.value


def toggle_help(self, e):

Expand Down
Loading

0 comments on commit afe9779

Please sign in to comment.