DrewNaylor / Retiled

An attempt at creating a "desktop" environment mainly for Linux phones and tablets that's similar in function to some parts of Microsoft's Windows Phone 8.x, primarily the Start screen, Search app, navigation bar, Action Center, and the status bar. Development is mainly being done using the PinePhone, so that'll be the main supported device.
https://codeberg.org/DrewNaylor/Retiled
Apache License 2.0
68 stars 3 forks source link

Extract appbar code from the Settings app into RetiledStyles + implement minimized appbars. #244

Closed DrewNaylor closed 1 year ago

DrewNaylor commented 1 year ago

Now apps can implement appbars and appbar drawers with basic boilerplate instead of copying and pasting the full implementation code. Please note that at the moment, there are some hardcoded IDs that must be used for page navigation to work:

You will also need to specify the root path of the pages you want to navigate to using the appbar and appbar drawer. Example code: Python (remember to hook it up to QML):

class AppRootPath(QObject):
    # We need to store the app's root directory
    # to refer to the pages so we can properly
    # navigate from the appbar and appbar drawer.
    @Slot(result=str)
    def getAppRootPath(self):
        # TODO: Change this to something more specific
        # so it doesn't break when the working directory
        # changes.
        return os.getcwd()

QML:

// Get the app root path for the appbar and appbar drawer pages.
readonly property string appRootPath: AppRootPath.getAppRootPath()

RetiledStyles.AppBarDrawer {
    // We need an ID for this because it's referred to from the appbar's code.
    // It has to be "appbarDrawer" for it to work.
    // TODO: Make it not require an ID.
    id: appbarDrawer
    // Note: There will eventually be more items than just an about page here.
    // TODO: Figure out how to make sure we stay in our app's path
    // instead of using the current working directory.
    // We have to use Component.onCompleted and ListModel.append
    // in order to grab stuff from the app's root path:
    // https://stackoverflow.com/a/33161093
    drawerItems: ListModel {
        // Now add stuff to the ListModel.
        // See the SO answer above the drawerItems line
        // for more details.
        Component.onCompleted: {
            append({ title: "about", navigate: "true", source: appRootPath + "/pages/About.qml" });
        }
    }
}

Other than that, here's the minimum implementation for adding an appbar and appbar drawer to your app. If it doesn't work because I forgot something, check either RetiledSettings or RetiledSearch. Note that this doesn't include navigation; that requires a StackView right now: QML:

footer: RetiledStyles.AppBar {
        // We need an ID for this because it's referred to from the appbar drawer's code.
        // It has to be "appBar" for it to work.
        // TODO: Make it not require an ID.
        id: appBar
        // A value of 0.1 makes it open just a little,
        // perfect for appbars without appbar drawer items
        // (but for now an empty appbar drawer will be required
        // as the appbar opening is tied to appbar drawers)
        // TODO: make appbar drawers not required.
        // This can be useful if you have a subpage that doesn't
        // need a drawer.
        //appbarOpenedHeightMultiplier: 0.1
        // Note: we need to add the appbar buttons eventually instead of just having nothing here.

        // For now we'll minimize the appbar until items are added to it.
        minimized: true
    }

    // Appbar stuff for the emergency back button and ellipsis button to be visible.
        // Use these to set their visibiloty instead of directly setting backButton.visible, for example.
    property bool backButtonVisible: false
    property bool appbarEllipsisButtonVisible: true

    // (the code from the block above continues here)
...

You can also set appbarDrawerHeight for appbar drawers to have the appbar drawer be a certain height when open (appbarDrawerHeight is a real [Qt's version of float] and defaults to 165), but be sure to set appbarOpenedHeightMultiplier for appbars so that the appbar and appbar drawer don't get their positioning messed up when open.

I've also implemented minimized appbars, and they will be half-height until the appbar drawer's position value is greater than 0.0, which isn't ideal (would prefer something smoother), but it works for now. So they'll be full-height when the appbar drawer isn't fully closed. Handling this is taken care of, so you just have to use minimized: true in the appbar to have yours be minimized when it's closed. It's important to note that the emergency back button uses the appbar, so it'll force itself into full-height mode even if the app says to minimize it. I also haven't yet added support for appbars (not counting the emergency back button) on subpages in any of my apps, so it may not work properly, but it might also be fine.

Additionally, I've set the appbar in both RetiledSearch and RetiledSettings to be minimized for now until I add buttons to them.