ethical-haquer / Galaxy-Flasher

A GUI for Samsung Flash Tools
GNU General Public License v3.0
42 stars 3 forks source link

Porting to LibAdwaita and publishing to Flathub #12

Open IverCoder opened 5 months ago

IverCoder commented 5 months ago

Is your feature request related to a problem? Please describe.

I have used this app a few times and it worked pretty well for me. However, it can use a bit of UI polish and more discoverability by being published on an app store. Few people unfortunately know about this nice piece of software, a bit more public exposure would be a big help.

Describe the solution you'd like.

The app can be ported to LibAdwaita for a quick and easy UI interface, use the XDG portals File Chooser and File Transfer for accessing the files to be flashed and facilitating drag and drop, and probably the Inhibit portal as well to prevent logging out or shutting down while flashing. Then the app can be submitted to Flathub.

Describe why the feature would be helpful

Flathub is the fastest-growing app store for desktop users, and LibAdwaita guarantees a nice UI compliant with GNOME's HIG for the best user experience.

Thor GUI version

Alpha v0.4.5

IverCoder commented 5 months ago

I hope I can help in this, but school's pretty busy and I don't think I have enough Python skills for this. Still, I hope this can be accomplished when the right time comes.

ethical-haquer commented 5 months ago

I hope I can help in this, but school's pretty busy and I don't think I have enough Python skills for this. Still, I hope this can be accomplished when the right time comes.

Thanks for the info! I'll have to start looking into porting it to LibAdwaita. As for Flathub, definitely! Currently, I'm working on improving the code that interacts with Thor, and adding odin4/heimdall support. But yes, hopefully it can be done at some point.

justaCasualCoder commented 5 months ago

If you end up using GTK4, this guide was super helpful for me when I made GTK4 stuff in Python.

justaCasualCoder commented 5 months ago

I was looking at porting to GTK4, but had a question. Would you want the GUI to stay the same?

ethical-haquer commented 5 months ago

I was looking at porting to GTK4, but had a question. Would you want the GUI to stay the same?

Wow, thanks for looking into it! I'm really not sure, honestly. Currently it looks similar to Odin, which could be considered a plus, as users will be able to follow tutorials that use Odin, but I do feel that it could be improved upon somehow. What do you think?

justaCasualCoder commented 5 months ago

I agree. I will look at this more later.

justaCasualCoder commented 5 months ago

I am currently stuck trying to position the widgets. Unfortunately, GTK does not have an equivalent to tk.Label.grid(**widget_grid_options). The GTK grid takes these arguments (from these docs):

  1. The child parameter is the Gtk.Widget to add.
  2. left is the column number to attach the left side of child to.
  3. top indicates the row number to attach the top side of child to.
  4. width and height indicate the number of columns that the child will span, and the number of rows that the child will span, respectively.

There is Gtk.Grid.add, but that just functions like Gtk.Box. This is the only way I can see to keep the current organization/creation of widgets (yes it is VERY messy; I made it in a few minutes):

import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw

class ToplevelWindow(Gtk.ApplicationWindow):
    def __init__(self, widgets, name):
        # INIT
        super().__init__(application=app)
        self.name = name + "_Window"
        self.widgets = widgets
        self.grid = Gtk.Grid()
        self.set_child(self.grid)
        self.create_widgets()
    def create_widgets(self):
        for widget in self.widgets:
            widget_type = widget["type"]
            widget_options = widget["options"]
            widget_grid_options = widget["grid_options"]
            if widget_type == "label":
                label = Gtk.Label()
                label.set_markup(widget_options["text"])
                self.grid.attach(label, widget_grid_options["pos1"], widget_grid_options["pos2"], widget_grid_options["pos3"], widget_grid_options["pos4"])
class ThorGUI(Adw.Application):
    def __init__(self, app_id, widgets, name):
        self.widgets = widgets
        self.name = name
        super().__init__(application_id=app_id)
        self.connect('activate', self.on_activate)
    def on_activate(self, app):
        self.win = ToplevelWindow(self.widgets, self.name)
        self.win.present()
widgets = [
    {
        "type": "label",
        "options": {
            "text": "<big>Thor Flash Utility v1.0.4</big>", 
        },
        "grid_options": {
            "pos1": 0,
            "pos2": 0,
            "pos3": 1,
            "pos4": 2,
        },
    }
]
app = ThorGUI("com.ethicalhaquer.thorgui", widgets, "Thor_GUI")
app.run(sys.argv)
justaCasualCoder commented 5 months ago

Do you think I should continue using that setup?

widgets = [
    {
        "type": "label",
        "options": {
            "text": "<big>Thor Flash Utility v1.0.4</big>", 
        },
        "grid_options": {
            "pos1": 0,
            "pos2": 0,
            "pos3": 1,
            "pos4": 2,
        },
    }
]
ethical-haquer commented 5 months ago

I am currently stuck trying to position the widgets. Unfortunately, GTK does not have an equivalent to tk.Label.grid(**widget_grid_options). The GTK grid takes these arguments (from these docs):

1. The `child` parameter is the [Gtk.Widget](https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Widget.html#Gtk.Widget) to add.

2. `left` is the column number to attach the left side of child to.

3. `top` indicates the row number to attach the top side of child to.

4. `width` and `height` indicate the number of columns that the child will span, and the number of rows that the child will span, respectively.

There is Gtk.Grid.add, but that just functions like Gtk.Box. This is the only way I can see to keep the current organization/creation of widgets (yes it is VERY messy; I made it in a few minutes):

import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw

class ToplevelWindow(Gtk.ApplicationWindow):
    def __init__(self, widgets, name):
        # INIT
        super().__init__(application=app)
        self.name = name + "_Window"
        self.widgets = widgets
        self.grid = Gtk.Grid()
        self.set_child(self.grid)
        self.create_widgets()
    def create_widgets(self):
        for widget in self.widgets:
            widget_type = widget["type"]
            widget_options = widget["options"]
            widget_grid_options = widget["grid_options"]
            if widget_type == "label":
                label = Gtk.Label()
                label.set_markup(widget_options["text"])
                self.grid.attach(label, widget_grid_options["pos1"], widget_grid_options["pos2"], widget_grid_options["pos3"], widget_grid_options["pos4"])
class ThorGUI(Adw.Application):
    def __init__(self, app_id, widgets, name):
        self.widgets = widgets
        self.name = name
        super().__init__(application_id=app_id)
        self.connect('activate', self.on_activate)
    def on_activate(self, app):
        self.win = ToplevelWindow(self.widgets, self.name)
        self.win.present()
widgets = [
    {
        "type": "label",
        "options": {
            "text": "<big>Thor Flash Utility v1.0.4</big>", 
        },
        "grid_options": {
            "pos1": 0,
            "pos2": 0,
            "pos3": 1,
            "pos4": 2,
        },
    }
]
app = ThorGUI("com.ethicalhaquer.thorgui", widgets, "Thor_GUI")
app.run(sys.argv)

Sorry for the late reply! I really have to read up on this. 🤣 I'm trying to think of what the proper way is for us to both work on this. I guess you'd just fork it?

Do you think I should continue using that setup?

widgets = [
    {
        "type": "label",
        "options": {
            "text": "<big>Thor Flash Utility v1.0.4</big>", 
        },
        "grid_options": {
            "pos1": 0,
            "pos2": 0,
            "pos3": 1,
            "pos4": 2,
        },
    }
]

Yeah, I think it looks good. 👍

ethical-haquer commented 5 months ago

I'm not sure if you already know, but I've been working on the pyte-test branch lately. As the name suggests, I'm experimenting with using pyte to display and detect the output from Thor (and soon odin4). Also I'm working on pyautocapture which I plan on using to keep the screenshots and screen-recording up-to-date. It's probably not the highest priority, but I was delaying until I got my S5 for doing more work on the pyte-test branch (It just got here today).

ethical-haquer commented 5 months ago

I just noticed your fork. 🤣

justaCasualCoder commented 5 months ago

Update: I'm working on this, I just don't want to update the fork until I have a solid base. I have been looking into using Gtk.Stack and Gtk.StackSwitcher for the tabs. Haha this is not super easy because there is like 0 documentation of GTK4 in Python. Update #2: This is how it's looking: Thor_GUI_GTK

ethical-haquer commented 5 months ago

It's looking really nice, thanks again! Also, about that phone I got, It had a Verizon battery cover, but it turned out to be a G900A! :rofl: I asked you some questions on your temporary unlock XDA thread.

justaCasualCoder commented 5 months ago

New Update: Yay! An About dialog! image image

ethical-haquer commented 5 months ago

New Update: Yay! An About dialog! image image

It looks like a legit app now. Wow 😮

justaCasualCoder commented 5 months ago

Do you think I should keep the current thor-gui.py file structure? Your implementation of thor-gui in tkinter has multiple functions that are unnecessary in GTK because it is more powerful. The structure of a GTK app is also very different... So there are 2 options:

  1. Keep the current thor-gui.py structure, deleting a few of the functions and patching the rest.
  2. Create a new thor-gui.py file, using the GTK structure.

I would prefer the latter option, but wanted your opinion.

justaCasualCoder commented 5 months ago

I think I found the perfect way to spawn thor in GTK: VTE! It auto scrolls, supports color, and allows sending commands to the child process (and reading back output).

ethical-haquer commented 5 months ago

Do you think I should keep the current thor-gui.py file structure? Your implementation of thor-gui in tkinter has multiple functions that are unnecessary in GTK because it is more powerful. The structure of a GTK app is also very different... So there are 2 options:

1. Keep the current `thor-gui.py` structure, deleting a few of the functions and patching the rest.

2. Create a new `thor-gui.py` file, using the `GTK` structure.

I would prefer the latter option, but wanted your opinion.

First of all, sorry for my delayed reply! (I've been out in the boonies)

Yeah, there's no need to keep the current structure. Definitely option 2. It needs a re-structuring anyways.

I think I found the perfect way to spawn thor in GTK: VTE! It auto scrolls, supports color, and allows sending commands to the child process (and reading back output).

I know, it's exactly what we need! Just VTE alone makes switching to GTK a no-brainer.

justaCasualCoder commented 5 months ago

Currently having issues setting up VTE. There is a TON of docs for GTK3, but not 4. If anyone happens to have a example/docs for VTE in GTK4, that would be great...

justaCasualCoder commented 5 months ago

Update: Finally got VTE and GTK4 working in Python! Probably going to work on it more tomorrow...

justaCasualCoder commented 4 months ago

I updated my fork! It has a LOT of features that don't work at all. Like no dialog's etc. The basic flashing functionality is almost done. My fork is here.

ethical-haquer commented 4 months ago

I updated my fork! It has a LOT of features that don't work at all. Like no dialog's etc. The basic flashing functionality is almost done. My fork is here.

It works great! I can't believe how much smaller the code is; GTK is definitely more powerful. You just forgot to add yourself to the credits! 😉

I sent you an invite to collaborate on Thor_GUI. I'm assuming the best course of action is to create a new Thor_GUI branch, something like "gtk", and then we can both work on it. What do you think?

justaCasualCoder commented 4 months ago

Yeah, that sounds like a good idea 👍

ethical-haquer commented 4 months ago

Yeah, that sounds like a good idea 👍

Alright, the new branch is ready.

justaCasualCoder commented 4 months ago

Currently working on porting the scan_output and select_partitions functions. Unfortunately, VTE does not have a signal for when output is updated. The contents-changed signal kinda works, but it is also called when the terminal is scrolled, causing all kinds of issues... I have gotten the select_partitions function working pretty well, but if you scroll in the terminal while it is running, ~20 select_partitions windows pop up :stuck_out_tongue:...

justaCasualCoder commented 4 months ago

Also I just responded to your question on my XDA thread. EDIT1: Haha oops accidentally clicked the close with comment button :laughing: ...

justaCasualCoder commented 4 months ago

Just added flashing functionality to the gtk branch! If anyone want's to help, just look for # TODO ... in thor-gui.py.

ethical-haquer commented 4 months ago

Just added flashing functionality to the gtk branch! If anyone want's to help, just look for # TODO ... in thor-gui.py.

Nice! I'd like to start working on it, but I get this error with the latest gtk branch:

Traceback (most recent call last):
  File "/home/ethical_haquer/GitHub/Thor_GUI/thor-gui.py", line 253, in scan_output
    terminal_text = vte.get_text_range_format(Vte.Format(1), 0, 0, 10000, 10000)[0]
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Terminal' object has no attribute 'get_text_range_format'

I can't find anything online, maybe I don't have something installed? I honestly have no idea. What are you developing this on? TIA.

justaCasualCoder commented 4 months ago

Just added flashing functionality to the gtk branch! If anyone want's to help, just look for # TODO ... in thor-gui.py.

Nice! I'd like to start working on it, but I get this error with the latest gtk branch:

Traceback (most recent call last):
  File "/home/ethical_haquer/GitHub/Thor_GUI/thor-gui.py", line 253, in scan_output
    terminal_text = vte.get_text_range_format(Vte.Format(1), 0, 0, 10000, 10000)[0]
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Terminal' object has no attribute 'get_text_range_format'

I can't find anything online, maybe I don't have something installed? I honestly have no idea. What are you developing this on? TIA.

You need to have VTE 3.9.1, and GTK 4.12. I was working on Debian, but switched to Arch because packages were newer. GTK is always removing/renaming functions. For a while between 4.10 and 4.12 there was like no file dialog :laughing: ... get_text_range_format was added in 0.72. These are the Debian package versions:

Package gir1.2-vte-3.91 bookworm (stable) (introspection): GObject introspection data for the VTE library ~0.70.6-2~deb12u1: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x trixie (testing) (introspection): GObject introspection data for the VTE library 0.75.91-2: amd64 arm64 armel armhf i386 mips64el ppc64el s390x sid (unstable) (introspection): GObject introspection data for the VTE library 0.75.92-1: amd64 arm64 armel armhf i386 m68k mips64el ppc64 ppc64el riscv64 s390x 0.75.91-2 [debports]: hppa sh4 0.74.2-1 [debports]: alpha ia64 sparc64 x32

EDIT1: These are the docs for PyGObject.

ethical-haquer commented 4 months ago

Just added flashing functionality to the gtk branch! If anyone want's to help, just look for # TODO ... in thor-gui.py.

Nice! I'd like to start working on it, but I get this error with the latest gtk branch:

Traceback (most recent call last):
  File "/home/ethical_haquer/GitHub/Thor_GUI/thor-gui.py", line 253, in scan_output
    terminal_text = vte.get_text_range_format(Vte.Format(1), 0, 0, 10000, 10000)[0]
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Terminal' object has no attribute 'get_text_range_format'

I can't find anything online, maybe I don't have something installed? I honestly have no idea. What are you developing this on? TIA.

You need to have VTE 3.9.1, and GTK 4.12. I was working on Debian, but switched to Arch because packages were newer. GTK is always removing/renaming functions. For a while between 4.10 and 4.12 there was like no file dialog 😆 ... get_text_range_format was added in 0.72. These are the Debian package versions:

Package gir1.2-vte-3.91 bookworm (stable) (introspection): GObject introspection data for the VTE library ~0.70.6-2~deb12u1: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x trixie (testing) (introspection): GObject introspection data for the VTE library 0.75.91-2: amd64 arm64 armel armhf i386 mips64el ppc64el s390x sid (unstable) (introspection): GObject introspection data for the VTE library 0.75.92-1: amd64 arm64 armel armhf i386 m68k mips64el ppc64 ppc64el riscv64 s390x 0.75.91-2 [debports]: hppa sh4 0.74.2-1 [debports]: alpha ia64 sparc64 x32

EDIT1: These are the docs for PyGObject.

Thanks for the reply! I saw those docs, but I thought I had version 3.91 (way newer, right? :rofl:), but yeah, I actually had 0.70.6. :facepalm: I've upgraded to Debian Testing, and now have the newer packages I need. Thanks again!

justaCasualCoder commented 4 months ago

Update: I am working on my Rust projects right now, but I still want to help with this. I will probably start working on it more in ~1 week.

ethical-haquer commented 4 months ago

Update: I am working on my Rust projects right now, but I still want to help with this. I will probably start working on it more in ~1 week.

Sounds good, I'm working on pyautocapture currently. (It's funny, I just used UxPlay yesterday on my Pi. It works well.)

justaCasualCoder commented 4 months ago

Update: I just fixed the stuff for toggling command entry visibility from icon press in the gtk branch.

ethical-haquer commented 4 months ago

Update: I just fixed the stuff for toggling command entry visibility from icon press in the gtk branch.

It works well, thanks! Are you planning to work on something else? (I just don't want to accidentally work on something you're planning to do)

justaCasualCoder commented 4 months ago

@ethical-haquer I will probably work on implementing the device chooser. Something else that really needs to be implemented is configuration saving... Adding the sudo/no sudo option will only work after that's been done.

ethical-haquer commented 4 months ago

@ethical-haquer I will probably work on implementing the device chooser. Something else that really needs to be implemented is configuration saving... Adding the sudo/no sudo option will only work after that's been done.

👍 Alright, I'll work on configuration saving.

justaCasualCoder commented 4 months ago

Update: Implemented the device chooser in the gtk branch.

justaCasualCoder commented 4 months ago

Here is a list of things that could be worked on:

I was thinking that a Github Projects board could help organize the things to do... What do you think?

ethical-haquer commented 4 months ago

The device chooser code looks great! I'm traveling right now, and I only have my S5, but I'll be back in a couple of days. Yeah, the GitHub Projects page is a good idea. Feel free to work on any of those things, including the Projects board. (OFC you don't have to ask to work on something, but I'm just saying you don't have to wait)

justaCasualCoder commented 4 months ago

@ethical-haquer I invited you to the Github Projects page. Here it is. I also just finished working on support for Flashing multiple files so that should work now.

ethical-haquer commented 4 months ago

I just added configuration saving! Also, what does "Estimate" mean for GitHub Projects? (sorry for the noob question 😊)

ethical-haquer commented 4 months ago

I worked on it some more! It's nearly at the same level that it was before the re-write. Adding odin4 support will be interesting. Most of the code should be the same, we just need to make it modular so that adding support for other flash tools is easy. Also, the name will have to be changed, if we're going to support multiple flash tools. I had thought of "Vidar" before. That's what my Python re-write of Thor was going to be called. What do you think?

justaCasualCoder commented 4 months ago

I worked on it some more! It's nearly at the same level that it was before the re-write. Adding odin4 support will be interesting. Most of the code should be the same, we just need to make it modular so that adding support for other flash tools is easy. Also, the name will have to be changed, if we're going to support multiple flash tools. I had thought of "Vidar" before. That's what my Python re-write of Thor was going to be called. What do you think?

That sounds like a good idea! Having support for odin4 would be great for the occasional issue with Thor. We could name it "Vidar" if we don't want to rewrite Thor in Python someday. About that, I managed to (using pyusb) connect, begin a session, and read/parse the PIT in Python over the last few days. I am really close to flashing a file, just having a few issues. Renaming is a good idea though because if we put this on Flathub, we'll probably want a name/logo for it.

I just added configuration saving! Also, what does "Estimate" mean for GitHub Projects? (sorry for the noob question 😊)

It's the estimated time you think it will take.

ethical-haquer commented 4 months ago

I worked on it some more! It's nearly at the same level that it was before the re-write. Adding odin4 support will be interesting. Most of the code should be the same, we just need to make it modular so that adding support for other flash tools is easy. Also, the name will have to be changed, if we're going to support multiple flash tools. I had thought of "Vidar" before. That's what my Python re-write of Thor was going to be called. What do you think?

That sounds like a good idea! Having support for odin4 would be great for the occasional issue with Thor. We could name it "Vidar" if we don't want to rewrite Thor in Python someday. About that, I managed to (using pyusb) connect, begin a session, and read/parse the PIT in Python over the last few days. I am really close to flashing a file, just having a few issues. Renaming is a good idea though because if we put this on Flathub, we'll probably want a name/logo for it.

That's really cool that you're making a new flash tool. Especially if it can be made cross-platform.

Okay, we'll save Vidar for the flash tool then. (if that's what you want to call it)

Let me know if you think of any names for the GUI.

EDIT: Oops! 😊

ethical-haquer commented 3 months ago

I just noticed your commits! 🤣 I was working on this code that uses FileDialog. Do we want to use this or stick with FileChooserNative?

def open_file(self, partition):
        def file_dialog_callback(obj, result):
            try:
                file = obj.open_finish(result)
                if file:
                    file_path = file.get_path()
                    print(f"Selected file: {file_path}")
                    entry = getattr(self, f"{partition}_entry")
                    entry.set_text(file_path)
            except GLib.Error as e:
                # If the user cancelled, pass.
                if e.code == 2:
                    pass
                else:
                    print(f"Error: {e}")
        file_dialog = Gtk.FileDialog(title=f"Select a {partition} file")
        odin_filter = Gtk.FileFilter()
        odin_filter.set_name("ODIN files")
        odin_filter.add_mime_type("application/x-tar")
        odin_filter.add_pattern("*.tar.md5")
        odin_filter.add_pattern("*.tar")
        filter_list = Gio.ListStore.new(Gtk.FileFilter)
        filter_list.append(odin_filter)
        file_dialog.set_filters(filter_list)
        file_dialog.open(self, None, file_dialog_callback)
justaCasualCoder commented 3 months ago

@ethical-haquer I switched to FileChooserNative because that's what the Flatpak XDG docs said to use (it uses XDG portal), but I just noticed that it's deprecated. If FileDialog works in Flatpak, then it would definitely be a better choice. EDIT: Just tested it in Flatpak, it works great! Using Gtk.FileDialog is definitely a better idea!

justaCasualCoder commented 3 months ago

@ethical-haquer How do you think we should add support for Odin4? Unlike Thor, it doesn't have an interactive cli... It would be good to make FlashTool's more modular so that adding new ones is easier...

ethical-haquer commented 3 months ago

@ethical-haquer How do you think we should add support for Odin4? Unlike Thor, it doesn't have an interactive cli... It would be good to make FlashTool's more modular so that adding new ones is easier...

We'll really just have to try out different things, see what's different between the two implementations, and then make it more modular. It'll be easier to see what needs to be done to make it modular once we've tried adding a new flash-tool, if you know what I mean.

About it not being interactive, the biggest thing is keeping a scroll-back of the commands that were run. Probably we'll just use a text widget, start a sub-process, and get it's output. Or maybe there's a better way to do that in GTK.

Also, I came up with a possible option for the name, "Galaxy Flasher". I'm sure you've heard of Pixel Flasher, the GUI interface for doing stuff with Pixels. I'm not sure if there would be issues with having "Galaxy" in the name though. Anyway, let me know how you feel about it (honestly).

justaCasualCoder commented 3 months ago

@ethical-haquer Sounds like a good name (honestly)! Like you said though, having "Galaxy" in it may cause issues. You own the project though, so do whatever you want.

ethical-haquer commented 3 months ago

@ethical-haquer Sounds like a good name (honestly)! Like you said though, having "Galaxy" in it may cause issues. You own the project though, so do whatever you want.

Sounds good! I had thought Aurora Store had to rename from Galaxy Store because of Samsung, but that isn't the case. As for me owning the project, that might be true, but I still want you to have a say in things. After all, I really appreciate your help, thank you!