Schedule & re-Schedule any action with Dynamic Date parsing

One thing is clear when launching a Product: timelines will change. 

To handle all these changes with ease, MarsManaged now includes Dynamic Date parsing*. Just type the target date in your own words and MarsManaged will do the rest.

Here it is in action: 

LaunchToVenus2

Here’s some examples of keywords you can use:

  • today (i.e. Did John send the minutes as discussed today @todo )
  • tomorrow 
  • this week
  • next week
  • thursday
  • next Friday
  • May
  • next month (i.e. Submit updated financials to C-Sec next month @todo )
  • next October
  • this year
  • next year

And, of course, once a date has been set you can change it directly in text or using the built in calendar popup (yes, that’s new too!). 

LaunchToVenus3

Everything is kept in sync: the ACTION date, the ACTION text and -of course- the CARD its linked to. 

Screen Shot 2022 05 22 at 9 27 31 PM

With this superpower there will not be more missed timelines, only changed timelines. Now, that’s how you make a Product Manager successful!

 

For users in TestFlight, the new beta should be rolling out very soon. If you want to be part of TestFlight and help shape the future of MarsManaged, drop me a line at contact@mmvsolucions.com

Thoughts, suggestions? Reach me @MarcMasVi

Marc

 

* yes, I totally made that name up. 

Adding an overlay when there’s no content to show – SwiftUI Empty States

Empty states. Or to put it another way, what do you show when a view is devoid of any content? 

This is an area that not all apps account for. The ones that do though, not only improve the end-user experience but also feel more… complete? 

Here’s some examples of empty states.

1. NetNewsWire (a great RSS reader that I use daily): 

Screen Shot 2022 04 16 at 12 53 53 PM

2. MarsEdit (my blogging app of choice):

Screen Shot 2022 04 16 at 12 53 20 PM

3. Evernote has a different style, showing also an image and a button to trigger next steps:

Screen Shot 2022 04 16 at 1 02 19 PM

4. Finally, here’s how Apple Notes approaches it:

Screen Shot 2022 04 16 at 2 44 14 PM

For MarsManaged I decided to go with a similar approach to Apple Notes when the card list is empty. Here’s how to easily do it in SwiftUI. 

1. Create a ZStack where you’ll have a list of items you want to show followed by your desired empty state view, in this case I’m using Text. 

2. Set the State View opacity to 1 if there’s no data to show or 0 otherwise. In doing so the view will only appear when there’s nothing to show. 

ZStack{

    List(){

        ForEach(notes){note in

                //Stuff […]

            }

        }

    Text(“No Cards”)

        .font(.title)

        .opacity(notes.count == 0 ? 1 : 0

}

In addition, to help infuse some character into the app I’m planning on having quotes related to space exploration/mars in the detail view. Maybe also some image of Mars? Have not decided yet… Do let me know what you think. 

Screen Shot 2022 04 16 at 2 58 53 PM

Development-wise it’s even easier: using an if statement it checks if a Card is selected and if so it’ll show the editor, else it’ll show the empty state view.  

Thoughts, suggestions? Reach me @MarcMasVi

Marc

Creating a macOS “About” screen the SwiftUI way

If you’re creating a macOS app, the About screen is that place where you get to “sign” your work. It is also the place where most developers will link to their personal web, thank contributors, etc. 

For me, it’s one of the areas I work on last… When I get to it, it always feels great. 

And here’s one of the areas where leveraging SwiftUI pays big time. It could not be easier:

1. In Xcode Create a new file and choose “Rich Text File”

Screen Shot 2022 04 05 at 11 09 31 AM

2. Name it “Credits”

3. Select the file you’ve just created and add the text you want. Be sure to center it. 

Screen Shot 2022 04 05 at 11 21 34 AM

4. Compile & Run

Screen Shot 2022 04 05 at 11 21 50 AM

That’s it, happy shipping! Thoughts, suggestions? Reach me @MarcMasVi

Marc

 

PS. Here’s the link to Apple Documentation

Badges? Gray Badges? Color Badges!

As I was working on cell badges indicating the number of to-dos pending for a given card it hit me… 

 The approach I was taking was good, it gave relevant and timely information…

MarcMasVi 2022 Apr 02

But could be much better: what if the flag changes color when you have a to-do overdue, due today, tomorrow or soon?  

This would, without increasing complexity, add context and allow the user to focus on what matters.  Furthermore, I could use the same split & colors already in use for to-dos, making it extremely accessible:

Screen Shot 2022 04 03 at 10 06 57 AM

Got to work, and a couple hours later, voilà:

Screen Shot 2022 04 02 at 9 08 09 PM

Quick aside for interested fellow engineers, this is pure SwiftUI. When the cell is loaded, a model helper function determines the number and color of to-dos. SwiftUI takes care of the rest and dynamically shows the right thing. 

Finally, if no to-dos exist for that card, no badge is shown. So, if you see no flags, you’re all done!

* * *

Here it is, in all its glory:

BadgeTodoitled1

* * *

On a side note, although I believe this to be a better experience for most users, some may prefer a cleaner aesthetic. For them I’ve added a preference toggle so they can disable them.

Screen Shot 2022 04 03 at 10 47 30 AM

* * *

At this point the app is almost feature-complete, I’m fully focused on polishing towards alpha -a very polished alpha that is-. If you’d like to be part of the test group do drop me a line at contact@mmvsolucions.com, would love your feedback.

Until next time! Thoughts, suggestions? Reach me @MarcMasVi

Marc

TextField Recommendations / Autocomplete – SwiftUI macOS and iOS

Another weekend, another set of improvements for MarsManaged. This time, I focused on adding an autocompletion feature for Tags.

Let me provide some context first… In MarsManaged, cards may be linked to one or multiple tags. In the below example, the “Welcome to MarsManaged!” card is linked to the tag “Samples” (yellow arrow). 

Screen Shot 2022 03 20 at 8 18 10 PM

To link one card to more tags, a user can start directly typing on the “+Tag” TextField. Once the user presses enter, the system will either link it to the right tag or —if it does not exist— create a new one and link it. 

To streamline the process, I wanted recommendations to start appearing once the user started typing.

– The bad news is that there’s no built-in SwiftUI methods for it.

– The good news is that by leveraging .onChange and .popover you can get the same functionality:

AutompleteExample

Here’s the section of the code that generates it:

@State private var popupTagsPresented = false

 

TextField(“PlaceholderText”, text: $variableLinkedTo)

.onChange(of: variableLinkedTo, perform: { newTag in

    //Do something with new tag to know when you want to show or not the popup, here assuming always

    popupTagsPresented = true

})

.popover(isPresented: $popupTagsPresented, arrowEdge: .top) {

    let filteredMatches = [“some stuff”, “somethingElse”]//Array of items to show (likely you’d grab it from Core Data / some model function)

    VStack(alignment: .leading, spacing: 4){

        ForEach(filteredMatches) { suggestion in

            Button{

                //When user clicks on the suggestion, replace text with suggestion and process it

                variableLinkedTo = suggestion.name

                processText()

            }label: {

                Label(suggestion.name ?? “”, systemImage: “someIcon”)

            }

            .buttonStyle(.borderless)

        }

    }.padding(10)

}

The above code uses .onChange to detect when the user starts typing in the TextField and flips the popupTagsPresented to true, which in turn shows the popover. 

The popover then displays the array of suggestions, each of them being its own Button. When a suggestion button is clicked, the TextField text is replaced by the selected suggestion and a function processText() is called. For my use case that function will link the tag to the card and then reset the TextField to nil so it’s ready to take new user input. 

Screen Shot 2022 03 20 at 8 35 44 PM

Happy Coding! Thoughts, suggestions? Reach me @MarcMasVi

 

Marc

MarsManaged March update, Alpha coming soon?

Lots of progress the last couple of weeks, the first alpha should be ready… Soon? 

Hard to predict.

What’s **not** hard to do is cover some of the features added last week. First, based on customer feedback, lots of work around Tags:

     – They can now include a template. If you create a Card while a Tag is selected,  it will default to that template. 

     – Tags can now be pinned, so you can easily access what’s most useful to you. 

     – Tag icons can now be changed, choose from over 100 options. 

Screen Shot 2022 03 13 at 10 18 32 PM

Also quite a bit of work went to the Settings Page. In addition to changing defaults, it allows users to easily modify the templates of Tags. 

Screen Shot 2022 03 13 at 10 22 17 PM

Finally, a lot of under the hood engine improvements for To-Dos. Its **crazy fast**

Screen Shot 2022 03 13 at 10 38 53 PM

Will post more soon to deep dive on the app key features, experience & more. So far the feedback has been very positive, can’t wait to get it in the hands of more users. 

If you’d like to participate in the Alpha -when its ready- do drop me a line at contact@mmvsolucions.com

Marc

SwiftUI macOS Preference Pane | Preferences

As easy as 1, 2, 3. Or is it?

1. Create a new SwiftUI file called PreferencePane and add the desired view within a TabView:

import SwiftUI

 

struct PreferencePane: View {

    var body: some View {

        

        TabView {

            Group{

                //ContentsOf the preferences view

                Text(“Profile Settings”)

            }

            .tabItem {

                Label(“General”, systemImage: “gearshape”)

            }

        

            

        }

        .frame(width: 500, height: 280)

        

    }

}

 

2. In your @main app add the following under WindowGroup:  #if os(macOS)… 

import SwiftUI

 

@main

struct NameApp: App {

 

    var body: some Scene {

        

        WindowGroup {

            SomeView

                .environment(\.managedObjectContext, persistenceController.container.viewContext)

 

        }

        

         #if os(macOS)

        Settings {

            PreferencePane()

        }

        #endif

    }

}

 

3. Compile & enjoy!

Screen Shot 2022 03 09 at 5 34 51 PM

Turns out, it was that easy. Done and done!

 

Thoughts, suggestions? Reach me @MarcMasVi

 

Marc

Expanding TO-DO views for MarsManaged

This weekend I continued working on the TO-DO area, specifically on bringing the context-aware functionality of Cards to “Target Date” & “Last Modified” views. 

As most of the code complexities were sorted last weekend, this one I did quite a bit of progress. Here’s the latest:

“Sort by Target Date” view:

Screen Shot 2022 02 06 at 11 04 04 AM

 

“Sort by Last Modified” view:

Screen Shot 2022 02 06 at 11 04 19 AM

In addition to the above improvements, there’s many other tweaks too. Here’s a few examples:

     – Double clicking on the note title takes you directly to the note the TO-DO belongs to. 

     – TO-DOs will only show Smart Dates (’Today’, ’Tomorrow’, ‘Overdue’) if they have not been completed. 

     – On the ‘Sort by Target Date’ view, dates will not appear on the Overdue, Today or Tomorrow sections.

 

And finally, worked a bit on the CARD search functionality. Now, when searching, an option appears for you to easily narrow search to the category/tag you have selected.  

Screen Shot 2022 02 06 at 12 57 54 PM

Thoughts, suggestions? Reach me @MarcMasVi

 

Marc

Working on all new TO-DO views for MarsManaged

This weekend I focused on the TO-DOS view of MarsManaged.

Instead of a list, as I originally developed it, working on having multiple context-aware options. In the example below showing the ’Sort by Card’ one, seems to me this makes this view a lot more useful than a list? 

In light mode:

Screen Shot 2022 01 30 at 8 21 15 PM

And dark mode:

Screen Shot 2022 01 30 at 8 11 21 PM

 

What you think? @MarcMasVi

 

Marc