Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Super-rough structure-only per-screen refactor #219

Draft
wants to merge 9 commits into
base: dev
Choose a base branch
from

Conversation

sjoerdverweij
Copy link
Collaborator

No description provided.

@lyricnz lyricnz marked this pull request as draft January 7, 2025 08:46
@lyricnz lyricnz added the DO NOT MERGE Work in progress not ready to be considered for merging label Jan 7, 2025

struct Feed {
public:
virtual String& getName();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the name required?
I'd say that 'id' would be enough.

and a nit: this is indented with 3 spaces.

Copy link
Collaborator Author

@sjoerdverweij sjoerdverweij Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need some kind of name to show in the config UI. Whether this is the best way to do it is debatable, I am open to suggestions.

(Alternately, we could have a big switch somewhere that names Ids, but that makes it easy for Orb authors to forget...)

};

struct Feed {
public:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public is not needed in a struct as first item, everything in a struct is public by default

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget that all the time, so I like to be explicit. If we decide it's an enforced style thing, no problem, I'll take it out.

Comment on lines +9 to +16
enum OrbId
{
OrbDateTimeWeekday = 1,
OrbCityWeatherPrediction = 2,
OrbWeatherIcon = 3,
OrbTemperatureHighLow = 4,
OrbWeather3DayForecast = 5
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this allows to mix and match the orbs, which is a long-standing feature request:

enum class OrbId
{
    Invalid,

    Weather_DateTimeWeekday,
    Weather_CityPrediction,
    Weather_Icon,
    Weather_TemperatureHighLow,
    Weather_3DayForecast,

    Stocks_1,
    Stocks_2,
    Stocks_3,
    Stocks_4,
    Stocks_5,

    Clock_Hour_h,
    Clock_Hour_l,
    Clock_SecondsColon,
    Clock_Minute_h,
    Clock_Minute_l,
};

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the point of it, I just started with the weather widget -- are you saying you don't like the naming of the enum members?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so.

In cases like this, having a consistent style in naming pays off imo.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we need an enum? Why not a list of list-of instances? (with constuctor/factory parameters as required). Totally value pseudo-code

[
  [
    new Clock(mode=HourH),
    new Clock(mode=HourL),
    new Clock(mode=SecondsColon),
    new Clock(mode=SecondsH),
    new Clock(mode=SecondsL)
  ],
  [
    new Stock(symbol=whatever, currency=whatever, apikey=whateever),
    ...
  ],
  [
    new WeatherTemp(..., location=whatever),
    new WeatherRain(..., location=whatever),
    new WeatherThing(..., location=whatever),
    ...
  ]
]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we need something in the UI, ya

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the UI, and in the config files / web editor / whatever is used to configure this thing.
You can't really transmit class instances over the web ;)

@dreed47
Copy link
Contributor

dreed47 commented Jan 8, 2025

I like the overall design direction. I have a couple logical model recommendations.

  1. A Gadget represents 5 Orbs but as I see it it needs to support both pre-defined Orb sets like clock and also mix/match user defined Orb sets. I'd recommend abstracting out a ContentSet class. Then maybe rename Gadget to ContentManager. So the ContentManager manages a collection of ContentSets and allow switching between them. So the ContentManager manages both predefined and user-defined ContentSets, handle button interations to cycle through the ContentSets and provides methods for creating, updating, and saving user-defined ContentSets.

  2. Feeds - The ContentManager (Gadget) should manage the lifecycle of the Feeds, ensure that Feeds are shared across all Orbs to reduce redundant data fetching, and dynamically load Feeds when needed by one or more Orbs. Also Feeds should make use of TaskManager/TaskFactory when getting data from external APIs

  3. Button Handling - ContentManager (Gadget) should specifically manage cycling of ContentSets via left/right button clicks.

  4. Renderer - The ContentManager (gadget) should coordinate with the Renderer to draw the active ContentSet on the 5 displays. Each Orb in the active ContentSet should use the Renderer to draw its content on the appropriate display.

  5. Need support for persistence for User-Defined ContentSets? to non-volatile storage? then would need methods for loading saved ContentSets on startup

@sjoerdverweij
Copy link
Collaborator Author

I like the overall design direction. I have a couple logical model recommendations.

  1. A Gadget represents 5 Orbs but as I see it it needs to support both pre-defined Orb sets like clock and also mix/match user defined Orb sets. I'd recommend abstracting out a ContentSet class. Then maybe rename Gadget to ContentManager. So the ContentManager manages a collection of ContentSets and allow switching between them. So the ContentManager manages both predefined and user-defined ContentSets, handle button interations to cycle through the ContentSets and provides methods for creating, updating, and saving user-defined ContentSets.
  2. Feeds - The ContentManager (Gadget) should manage the lifecycle of the Feeds, ensure that Feeds are shared across all Orbs to reduce redundant data fetching, and dynamically load Feeds when needed by one or more Orbs. Also Feeds should make use of TaskManager/TaskFactory when getting data from external APIs
  3. Button Handling - ContentManager (Gadget) should specifically manage cycling of ContentSets via left/right button clicks.
  4. Renderer - The ContentManager (gadget) should coordinate with the Renderer to draw the active ContentSet on the 5 displays. Each Orb in the active ContentSet should use the Renderer to draw its content on the appropriate display.
  5. Need support for persistence for User-Defined ContentSets? to non-volatile storage? then would need methods for loading saved ContentSets on startup

Gadget only needs to support configurable mix/match orb sets, because there really no longer is such a thing as a predefined widget; those are just default mix/match configurations. You'd start out with a configuration for a Gadget that has 4 instances of a ClockDigit orb, and one ClockSeconds orb. If we want to prevent users from changing the default settings, we can make them read-only -- but they will still work the exact same way.
Lifecycle and deduplication of Feeds is in the Feeds class. It should be a singleton, which it currently is not properly set up and referenced as.
Button handling etc.; I think Gadgets is what you want ContentManager to be.
Agreed, it will, the draw code isn't fleshed out yet.
I'm open to the best way to save settings. My current thinking is Serialize/Deserialize methods on the top of the settings hierarchy (Settings) which (de)serializes the global settings, then calls all its GadgetSettings, which then calls all its OrbSettings. (GadgetSettings holds which orbs a gadget shows, OrbSettings has the specific settings for that instance of the orb).

@lyricnz
Copy link
Collaborator

lyricnz commented Jan 10, 2025

Sorry I broke this PR merging #218

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DO NOT MERGE Work in progress not ready to be considered for merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants