Ejemplo n.º 1
0
def commit(args, modifier=None):
    from wunderlist.api import tasks
    from wunderlist.sync import background_sync

    task = _task(args)
    prefs = Preferences.current_prefs()

    prefs.last_list_id = task.list_id

    task_info = tasks.create_task(task.list_id, task.title,
                                  assignee_id=task.assignee_id,
                                  recurrence_type=task.recurrence_type,
                                  recurrence_count=task.recurrence_count,
                                  due_date=task.due_date,
                                  reminder_date=task.reminder_date,
                                  starred=task.starred,
                                  completed=task.completed,
                                  note=task.note)

    # Output must be a UTF-8 encoded string
    print ('The task was added to ' + task.list_title).encode('utf-8')

    if modifier == 'alt':
        import webbrowser

        webbrowser.open('wunderlist://tasks/%d' % task_info['id'])

    background_sync()
Ejemplo n.º 2
0
def commit(args, modifier=None):
    from wunderlist.api import lists
    from wunderlist.sync import background_sync

    list_name = _list_name(args)

    lists.create_list(list_name)

    print 'The new list was created'

    background_sync()
Ejemplo n.º 3
0
def commit(args, modifier=None):
    from wunderlist.api import lists
    from wunderlist.sync import background_sync

    list_name = _list_name(args)

    lists.create_list(list_name)

    print 'The new list was created'

    background_sync()
Ejemplo n.º 4
0
def filter(args):
    wf = workflow()
    prefs = Preferences.current_prefs()
    command = args[1] if len(args) > 1 else None

    # Show sort options
    if command == 'sort':
        for i, order_info in enumerate(_due_orders):
            wf.add_item(order_info['title'],
                        order_info['subtitle'],
                        arg='-due sort %d' % (i + 1),
                        valid=True,
                        icon=icons.RADIO_SELECTED if order_info['due_order']
                        == prefs.due_order else icons.RADIO)

        wf.add_item(
            'Highlight skipped recurring tasks',
            'Hoists recurring tasks that have been missed multiple times over to the top',
            arg='-due sort toggle-skipped',
            valid=True,
            icon=icons.CHECKBOX_SELECTED
            if prefs.hoist_skipped_tasks else icons.CHECKBOX)

        wf.add_item('Back', autocomplete='-due ', icon=icons.BACK)

        return

    # Force a sync if not done recently or wait on the current sync
    if not prefs.last_sync or \
       datetime.now() - prefs.last_sync > timedelta(seconds=30) or \
       is_running('sync'):
        sync()

    conditions = True

    # Build task title query based on the args
    for arg in args[1:]:
        if len(arg) > 1:
            conditions = conditions & (Task.title.contains(arg)
                                       | List.title.contains(arg))

    if conditions is None:
        conditions = True

    tasks = Task.select().join(
        List).where(Task.completed_at.is_null()
                    & (Task.due_date < date.today() + timedelta(days=1))
                    & Task.list.is_null(False) & conditions)

    # Sort the tasks according to user preference
    for key in prefs.due_order:
        order = 'asc'
        field = None
        if key[0] == '-':
            order = 'desc'
            key = key[1:]

        if key == 'due_date':
            field = Task.due_date
        elif key == 'list.order':
            field = List.order
        elif key == 'order':
            field = Task.order

        if field:
            if order == 'asc':
                tasks = tasks.order_by(field.asc())
            else:
                tasks = tasks.order_by(field.desc())

    try:
        if prefs.hoist_skipped_tasks:
            tasks = sorted(tasks, key=lambda t: -t.overdue_times)

        for t in tasks:
            wf.add_item(
                u'%s – %s' % (t.list_title, t.title),
                t.subtitle(),
                autocomplete='-task %s ' % t.id,
                icon=icons.TASK_COMPLETED if t.completed else icons.TASK)
    except OperationalError:
        background_sync()

    wf.add_item(u'Sort order',
                'Change the display order of due tasks',
                autocomplete='-due sort',
                icon=icons.SORT)

    wf.add_item('Main menu', autocomplete='', icon=icons.BACK)

    # Make sure tasks stay up-to-date
    background_sync_if_necessary(seconds=2)
Ejemplo n.º 5
0
def filter(args):
    wf = workflow()
    prefs = Preferences.current_prefs()
    command = args[1] if len(args) > 1 else None
    duration_info = _duration_info(prefs.upcoming_duration)

    if command == 'duration':
        selected_duration = prefs.upcoming_duration

        # Apply selected duration option
        if len(args) > 2:
            try:
                selected_duration = int(args[2])
            except:
                pass

        duration_info = _duration_info(selected_duration)

        if 'custom' in duration_info:
            wf.add_item(duration_info['label'], duration_info['subtitle'], arg='-upcoming duration %d' % (duration_info['days']), valid=True, icon=icons.RADIO_SELECTED if duration_info['days'] == selected_duration else icons.RADIO)

        for duration_info in _durations:
            wf.add_item(duration_info['label'], duration_info['subtitle'], arg='-upcoming duration %d' % (duration_info['days']), valid=True, icon=icons.RADIO_SELECTED if duration_info['days'] == selected_duration else icons.RADIO)

        wf.add_item('Back', autocomplete='-upcoming ', icon=icons.BACK)

        return

    # Force a sync if not done recently or join if already running
    if not prefs.last_sync or \
       datetime.now() - prefs.last_sync > timedelta(seconds=30) or \
       is_running('sync'):
        sync()

    wf.add_item(duration_info['label'], subtitle='Change the duration for upcoming tasks', autocomplete='-upcoming duration ', icon=icons.UPCOMING)

    conditions = True

    # Build task title query based on the args
    for arg in args[1:]:
        if len(arg) > 1:
            conditions = conditions & (Task.title.contains(arg) | List.title.contains(arg))

    if conditions is None:
        conditions = True

    tasks = Task.select().join(List).where(
        Task.completed_at.is_null() &
        (Task.due_date < date.today() + timedelta(days=duration_info['days'] + 1)) &
        (Task.due_date > date.today() + timedelta(days=1)) &
        Task.list.is_null(False) &
        conditions
    )\
        .join(Reminder, JOIN.LEFT_OUTER, on=Reminder.task == Task.id)\
        .order_by(Task.due_date.asc(), Reminder.date.asc(), Task.order.asc())

    try:
        for t in tasks:
            wf.add_item(u'%s – %s' % (t.list_title, t.title), t.subtitle(), autocomplete='-task %s ' % t.id, icon=icons.TASK_COMPLETED if t.completed else icons.TASK)
    except OperationalError:
        background_sync()

    wf.add_item('Main menu', autocomplete='', icon=icons.BACK)

    # Make sure tasks stay up-to-date
    background_sync_if_necessary(seconds=2)
Ejemplo n.º 6
0
def filter(args):
    query = ' '.join(args[1:])
    wf = workflow()
    prefs = Preferences.current_prefs()
    matching_hashtags = []

    if not query:
        wf.add_item('Begin typing to search tasks', '', icon=icons.SEARCH)

    hashtag_match = re.search(_hashtag_prompt_pattern, query)
    if hashtag_match:
        from wunderlist.models.hashtag import Hashtag

        hashtag_prompt = hashtag_match.group().lower()
        hashtags = Hashtag.select().where(
            Hashtag.id.contains(hashtag_prompt)).order_by(
                fn.Lower(Hashtag.tag).asc())

        for hashtag in hashtags:
            # If there is an exact match, do not show hashtags
            if hashtag.id == hashtag_prompt:
                matching_hashtags = []
                break

            matching_hashtags.append(hashtag)

    # Show hashtag prompt if there is more than one matching hashtag or the
    # hashtag being typed does not exactly match the single matching hashtag
    if len(matching_hashtags) > 0:
        for hashtag in matching_hashtags:
            wf.add_item(hashtag.tag[1:],
                        '',
                        autocomplete=u'-search %s%s ' %
                        (query[:hashtag_match.start()], hashtag.tag),
                        icon=icons.HASHTAG)

    else:
        conditions = True
        lists = workflow().stored_data('lists')
        matching_lists = None
        query = ' '.join(args[1:]).strip()
        list_query = None

        # Show all lists on the main search screen
        if not query:
            matching_lists = lists
        # Filter lists when colon is used
        if ':' in query:
            matching_lists = lists
            components = re.split(r':\s*', query, 1)
            list_query = components[0]
            if list_query:
                matching_lists = workflow().filter(
                    list_query,
                    lists if lists else [],
                    lambda l: l['title'],
                    # Ignore MATCH_ALLCHARS which is expensive and inaccurate
                    match_on=MATCH_ALL ^ MATCH_ALLCHARS)

                # If no matching list search against all tasks
                if matching_lists:
                    query = components[1] if len(components) > 1 else ''

                # If there is a list exactly matching the query ignore
                # anything else. This takes care of lists that are substrings
                # of other lists
                if len(matching_lists) > 1:
                    for l in matching_lists:
                        if l['title'].lower() == list_query.lower():
                            matching_lists = [l]
                            break

        if matching_lists:
            if not list_query:
                wf.add_item('Browse by hashtag',
                            autocomplete='-search #',
                            icon=icons.HASHTAG)

            if len(matching_lists) > 1:
                for l in matching_lists:
                    icon = icons.INBOX if l[
                        'list_type'] == 'inbox' else icons.LIST
                    wf.add_item(l['title'],
                                autocomplete='-search %s: ' % l['title'],
                                icon=icon)
            else:
                conditions = conditions & (Task.list
                                           == matching_lists[0]['id'])

        if not matching_lists or len(matching_lists) <= 1:
            for arg in query.split(' '):
                if len(arg) > 1:
                    conditions = conditions & (Task.title.contains(arg)
                                               | List.title.contains(arg))

            if conditions:
                if not prefs.show_completed_tasks:
                    conditions = Task.completed_at.is_null() & conditions

                tasks = Task.select().where(
                    Task.list.is_null(False) & conditions)

                # Default Wunderlist sort order reversed to show newest first
                tasks = tasks.join(List).order_by(Task.order.desc(),
                                                  List.order.asc())

                # Avoid excessive results
                tasks = tasks.limit(50)

                try:
                    for t in tasks:
                        wf.add_item(u'%s – %s' % (t.list_title, t.title),
                                    t.subtitle(),
                                    autocomplete='-task %s  ' % t.id,
                                    icon=icons.TASK_COMPLETED
                                    if t.completed else icons.TASK)
                except OperationalError:
                    background_sync()

            if prefs.show_completed_tasks:
                wf.add_item('Hide completed tasks',
                            arg='-pref show_completed_tasks --alfred %s' %
                            ' '.join(args),
                            valid=True,
                            icon=icons.HIDDEN)
            else:
                wf.add_item('Show completed tasks',
                            arg='-pref show_completed_tasks --alfred %s' %
                            ' '.join(args),
                            valid=True,
                            icon=icons.VISIBLE)

        wf.add_item('New search', autocomplete='-search ', icon=icons.CANCEL)
        wf.add_item('Main menu', autocomplete='', icon=icons.BACK)

        # Make sure tasks are up-to-date while searching
        background_sync()
Ejemplo n.º 7
0
def filter(args):
    prefs = Preferences.current_prefs()

    if 'reminder' in args:
        reminder_time = _parse_time(' '.join(args))

        if reminder_time is not None:
            workflow().add_item('Change default reminder time',
                                u'⏰ %s' % format_time(reminder_time, 'short'),
                                arg=' '.join(args),
                                valid=True,
                                icon=icons.REMINDER)
        else:
            workflow().add_item(
                'Type a new reminder time',
                'Date offsets like the morning before the due date are not supported yet',
                valid=False,
                icon=icons.REMINDER)

        workflow().add_item('Cancel', autocomplete='-pref', icon=icons.BACK)
    elif 'reminder_today' in args:
        reminder_today_offset = _parse_time(' '.join(args))

        if reminder_today_offset is not None:
            workflow().add_item('Set a custom reminder offset',
                                u'⏰ now + %s' %
                                _format_time_offset(reminder_today_offset),
                                arg=' '.join(args),
                                valid=True,
                                icon=icons.REMINDER)
        else:
            workflow().add_item('Type a custom reminder offset',
                                'Use the formats hh:mm or 2h 5m',
                                valid=False,
                                icon=icons.REMINDER)

        workflow().add_item('30 minutes',
                            arg='-pref reminder_today 30m',
                            valid=True,
                            icon=icons.REMINDER)

        workflow().add_item('1 hour',
                            '(default)',
                            arg='-pref reminder_today 1h',
                            valid=True,
                            icon=icons.REMINDER)

        workflow().add_item('90 minutes',
                            arg='-pref reminder_today 90m',
                            valid=True,
                            icon=icons.REMINDER)

        workflow().add_item(
            'Always use the default reminder time',
            'Avoids adjusting the reminder based on the current date',
            arg='-pref reminder_today disabled',
            valid=True,
            icon=icons.CANCEL)

        workflow().add_item('Cancel', autocomplete='-pref', icon=icons.BACK)
    elif 'default_list' in args:
        lists = workflow().stored_data('lists')
        matching_lists = lists

        if len(args) > 2:
            list_query = ' '.join(args[2:])
            if list_query:
                matching_lists = workflow().filter(
                    list_query,
                    lists,
                    lambda l: l['title'],
                    # Ignore MATCH_ALLCHARS which is expensive and inaccurate
                    match_on=MATCH_ALL ^ MATCH_ALLCHARS)

        for i, l in enumerate(matching_lists):
            if i == 1:
                workflow().add_item(
                    'Most recently used list',
                    'Default to the last list to which a task was added',
                    arg='-pref default_list %d' % DEFAULT_LIST_MOST_RECENT,
                    valid=True,
                    icon=icons.RECURRENCE)
            icon = icons.INBOX if l['list_type'] == 'inbox' else icons.LIST
            workflow().add_item(l['title'],
                                arg='-pref default_list %s' % l['id'],
                                valid=True,
                                icon=icon)

        workflow().add_item('Cancel', autocomplete='-pref', icon=icons.BACK)
    else:
        current_user = None
        lists = workflow().stored_data('lists')
        default_list_name = 'Inbox'

        try:
            current_user = User.get()
        except User.DoesNotExist:
            pass
        except OperationalError:
            from wunderlist.sync import background_sync
            background_sync()

        if prefs.default_list_id == DEFAULT_LIST_MOST_RECENT:
            default_list_name = 'Most recent list'
        else:
            default_list_id = prefs.default_list_id
            default_list_name = next(
                (l['title'] for l in lists if l['id'] == default_list_id),
                'Inbox')

        if current_user and current_user.name:
            workflow().add_item('Sign out',
                                'You are logged in as ' + current_user.name,
                                autocomplete='-logout',
                                icon=icons.CANCEL)

        workflow().add_item('Show completed tasks',
                            'Includes completed tasks in search results',
                            arg='-pref show_completed_tasks',
                            valid=True,
                            icon=icons.TASK_COMPLETED
                            if prefs.show_completed_tasks else icons.TASK)

        workflow().add_item(
            'Default reminder time',
            u'⏰ %s    Reminders without a specific time will be set to this time'
            % format_time(prefs.reminder_time, 'short'),
            autocomplete='-pref reminder ',
            icon=icons.REMINDER)

        workflow().add_item(
            'Default reminder when due today',
            u'⏰ %s    Default reminder time for tasks due today is %s' %
            (_format_time_offset(prefs.reminder_today_offset),
             'relative to the current time' if prefs.reminder_today_offset else
             'always %s' % format_time(prefs.reminder_time, 'short')),
            autocomplete='-pref reminder_today ',
            icon=icons.REMINDER)

        workflow().add_item(
            'Default list',
            u'%s    Change the default list when creating new tasks' %
            default_list_name,
            autocomplete='-pref default_list ',
            icon=icons.LIST)

        workflow().add_item(
            'Automatically set a reminder on the due date',
            u'Sets a default reminder for tasks with a due date.',
            arg='-pref automatic_reminders',
            valid=True,
            icon=icons.TASK_COMPLETED
            if prefs.automatic_reminders else icons.TASK)

        workflow().add_item(
            'Require explicit due keyword',
            'Requires the due keyword to avoid accidental due date extraction',
            arg='-pref explicit_keywords',
            valid=True,
            icon=icons.TASK_COMPLETED
            if prefs.explicit_keywords else icons.TASK)

        workflow().add_item(
            'Check for experimental updates to this workflow',
            'The workflow automatically checks for updates; enable this to include pre-releases',
            arg=':pref prerelease_channel',
            valid=True,
            icon=icons.TASK_COMPLETED
            if prefs.prerelease_channel else icons.TASK)

        workflow().add_item(
            'Force sync',
            'The workflow syncs automatically, but feel free to be forcible.',
            arg='-pref sync',
            valid=True,
            icon=icons.SYNC)

        workflow().add_item('Switch theme',
                            'Toggle between light and dark icons',
                            arg='-pref retheme',
                            valid=True,
                            icon=icons.PAINTBRUSH)

        workflow().add_item('Main menu', autocomplete='', icon=icons.BACK)
def filter(args):
    wf = workflow()
    prefs = Preferences.current_prefs()
    command = args[1] if len(args) > 1 else None
    duration_info = _duration_info(prefs.upcoming_duration)

    if command == 'duration':
        selected_duration = prefs.upcoming_duration

        # Apply selected duration option
        if len(args) > 2:
            try:
                selected_duration = int(args[2])
            except:
                pass

        duration_info = _duration_info(selected_duration)

        if 'custom' in duration_info:
            wf.add_item(duration_info['label'],
                        duration_info['subtitle'],
                        arg='-upcoming duration %d' % (duration_info['days']),
                        valid=True,
                        icon=icons.RADIO_SELECTED if duration_info['days']
                        == selected_duration else icons.RADIO)

        for duration_info in _durations:
            wf.add_item(duration_info['label'],
                        duration_info['subtitle'],
                        arg='-upcoming duration %d' % (duration_info['days']),
                        valid=True,
                        icon=icons.RADIO_SELECTED if duration_info['days']
                        == selected_duration else icons.RADIO)

        wf.add_item('Back', autocomplete='-upcoming ', icon=icons.BACK)

        return

    # Force a sync if not done recently or join if already running
    if not prefs.last_sync or \
       datetime.now() - prefs.last_sync > timedelta(seconds=30) or \
       is_running('sync'):
        sync()

    wf.add_item(duration_info['label'],
                subtitle='Change the duration for upcoming tasks',
                autocomplete='-upcoming duration ',
                icon=icons.UPCOMING)

    conditions = True

    # Build task title query based on the args
    for arg in args[1:]:
        if len(arg) > 1:
            conditions = conditions & (Task.title.contains(arg)
                                       | List.title.contains(arg))

    if conditions is None:
        conditions = True

    tasks = Task.select().join(List).where(
        Task.completed_at.is_null() &
        (Task.due_date < date.today() + timedelta(days=duration_info['days'] + 1)) &
        (Task.due_date > date.today() + timedelta(days=1)) &
        Task.list.is_null(False) &
        conditions
    )\
        .join(Reminder, JOIN.LEFT_OUTER, on=Reminder.task == Task.id)\
        .order_by(Task.due_date.asc(), Reminder.date.asc(), Task.order.asc())

    try:
        for t in tasks:
            wf.add_item(
                u'%s – %s' % (t.list_title, t.title),
                t.subtitle(),
                autocomplete='-task %s ' % t.id,
                icon=icons.TASK_COMPLETED if t.completed else icons.TASK)
    except OperationalError:
        background_sync()

    wf.add_item('Main menu', autocomplete='', icon=icons.BACK)

    # Make sure tasks stay up-to-date
    background_sync_if_necessary(seconds=2)
Ejemplo n.º 9
0
def filter(args):
    wf = workflow()
    prefs = Preferences.current_prefs()
    command = args[1] if len(args) > 1 else None

    # Show sort options
    if command == 'sort':
        for i, order_info in enumerate(_due_orders):
            wf.add_item(order_info['title'], order_info['subtitle'], arg='-due sort %d' % (i + 1), valid=True, icon=icons.RADIO_SELECTED if order_info['due_order'] == prefs.due_order else icons.RADIO)

        wf.add_item('Highlight skipped recurring tasks', 'Hoists recurring tasks that have been missed multiple times over to the top', arg='-due sort toggle-skipped', valid=True, icon=icons.CHECKBOX_SELECTED if prefs.hoist_skipped_tasks else icons.CHECKBOX)

        wf.add_item('Back', autocomplete='-due ', icon=icons.BACK)

        return

    # Force a sync if not done recently or wait on the current sync
    if not prefs.last_sync or \
       datetime.now() - prefs.last_sync > timedelta(seconds=30) or \
       is_running('sync'):
        sync()

    conditions = True

    # Build task title query based on the args
    for arg in args[1:]:
        if len(arg) > 1:
            conditions = conditions & (Task.title.contains(arg) | List.title.contains(arg))

    if conditions is None:
        conditions = True

    tasks = Task.select().join(List).where(
        Task.completed_at.is_null() &
        (Task.due_date < date.today() + timedelta(days=1)) &
        Task.list.is_null(False) &
        conditions
    )

    # Sort the tasks according to user preference
    for key in prefs.due_order:
        order = 'asc'
        field = None
        if key[0] == '-':
            order = 'desc'
            key = key[1:]

        if key == 'due_date':
            field = Task.due_date
        elif key == 'list.order':
            field = List.order
        elif key == 'order':
            field = Task.order

        if field:
            if order == 'asc':
                tasks = tasks.order_by(field.asc())
            else:
                tasks = tasks.order_by(field.desc())

    try:
        if prefs.hoist_skipped_tasks:
            tasks = sorted(tasks, key=lambda t: -t.overdue_times)

        for t in tasks:
            wf.add_item(u'%s – %s' % (t.list_title, t.title), t.subtitle(), autocomplete='-task %s ' % t.id, icon=icons.TASK_COMPLETED if t.completed else icons.TASK)
    except OperationalError:
        background_sync()

    wf.add_item(u'Sort order', 'Change the display order of due tasks', autocomplete='-due sort', icon=icons.SORT)

    wf.add_item('Main menu', autocomplete='', icon=icons.BACK)

    # Make sure tasks stay up-to-date
    background_sync_if_necessary(seconds=2)
Ejemplo n.º 10
0
def filter(args):
    prefs = Preferences.current_prefs()

    if 'reminder' in args:
        reminder_time = _parse_time(' '.join(args))

        if reminder_time is not None:
            workflow().add_item(
                'Change default reminder time',
                u'⏰ %s' % format_time(reminder_time, 'short'),
                arg=' '.join(args), valid=True, icon=icons.REMINDER
            )
        else:
            workflow().add_item(
                'Type a new reminder time',
                'Date offsets like the morning before the due date are not supported yet',
                valid=False, icon=icons.REMINDER
            )

        workflow().add_item(
            'Cancel',
            autocomplete='-pref', icon=icons.BACK
        )
    elif 'reminder_today' in args:
        reminder_today_offset = _parse_time(' '.join(args))

        if reminder_today_offset is not None:
            workflow().add_item(
                'Set a custom reminder offset',
                u'⏰ now + %s' % _format_time_offset(reminder_today_offset),
                arg=' '.join(args), valid=True, icon=icons.REMINDER
            )
        else:
            workflow().add_item(
                'Type a custom reminder offset',
                'Use the formats hh:mm or 2h 5m',
                valid=False, icon=icons.REMINDER
            )

        workflow().add_item(
            '30 minutes',
            arg='-pref reminder_today 30m', valid=True, icon=icons.REMINDER
        )

        workflow().add_item(
            '1 hour',
            '(default)',
            arg='-pref reminder_today 1h', valid=True, icon=icons.REMINDER
        )

        workflow().add_item(
            '90 minutes',
            arg='-pref reminder_today 90m', valid=True, icon=icons.REMINDER
        )

        workflow().add_item(
            'Always use the default reminder time',
            'Avoids adjusting the reminder based on the current date',
            arg='-pref reminder_today disabled', valid=True, icon=icons.CANCEL
        )

        workflow().add_item(
            'Cancel',
            autocomplete='-pref', icon=icons.BACK
        )
    elif 'default_list' in args:
        lists = workflow().stored_data('lists')
        matching_lists = lists

        if len(args) > 2:
            list_query = ' '.join(args[2:])
            if list_query:
                matching_lists = workflow().filter(
                    list_query,
                    lists,
                    lambda l: l['title'],
                    # Ignore MATCH_ALLCHARS which is expensive and inaccurate
                    match_on=MATCH_ALL ^ MATCH_ALLCHARS
                )

        for i, l in enumerate(matching_lists):
            if i == 1:
                workflow().add_item(
                    'Most recently used list',
                    'Default to the last list to which a task was added',
                    arg='-pref default_list %d' % DEFAULT_LIST_MOST_RECENT,
                    valid=True, icon=icons.RECURRENCE
                )
            icon = icons.INBOX if l['list_type'] == 'inbox' else icons.LIST
            workflow().add_item(
                l['title'],
                arg='-pref default_list %s' % l['id'],
                valid=True, icon=icon
            )

        workflow().add_item(
            'Cancel',
            autocomplete='-pref', icon=icons.BACK
        )
    else:
        current_user = None
        lists = workflow().stored_data('lists')
        loc = user_locale()
        default_list_name = 'Inbox'

        try:
            current_user = User.get()
        except User.DoesNotExist:
            pass
        except OperationalError:
            from wunderlist.sync import background_sync
            background_sync()

        if prefs.default_list_id == DEFAULT_LIST_MOST_RECENT:
            default_list_name = 'Most recent list'
        else:
            default_list_id = prefs.default_list_id
            default_list_name = next((l['title'] for l in lists if l['id'] == default_list_id), 'Inbox')

        if current_user and current_user.name:
            workflow().add_item(
                'Sign out',
                'You are logged in as ' + current_user.name,
                autocomplete='-logout', icon=icons.CANCEL
            )

        workflow().add_item(
            'Show completed tasks',
            'Includes completed tasks in search results',
            arg='-pref show_completed_tasks', valid=True, icon=icons.TASK_COMPLETED if prefs.show_completed_tasks else icons.TASK
        )

        workflow().add_item(
            'Default reminder time',
            u'⏰ %s    Reminders without a specific time will be set to this time' % format_time(prefs.reminder_time, 'short'),
            autocomplete='-pref reminder ', icon=icons.REMINDER
        )

        workflow().add_item(
            'Default reminder when due today',
            u'⏰ %s    Default reminder time for tasks due today is %s' % (_format_time_offset(prefs.reminder_today_offset), 'relative to the current time' if prefs.reminder_today_offset else 'always %s' % format_time(prefs.reminder_time, 'short')),
            autocomplete='-pref reminder_today ', icon=icons.REMINDER
        )

        workflow().add_item(
            'Default list',
            u'%s    Change the default list when creating new tasks' % default_list_name,
            autocomplete='-pref default_list ', icon=icons.LIST
        )

        workflow().add_item(
            'Automatically set a reminder on the due date',
            u'Sets a default reminder for tasks with a due date.',
            arg='-pref automatic_reminders', valid=True, icon=icons.TASK_COMPLETED if prefs.automatic_reminders else icons.TASK
        )

        if loc != 'en_US' or prefs.date_locale:
            workflow().add_item(
                'Force US English for dates',
                'Rather than the current locale (%s)' % loc,
                arg='-pref force_en_US', valid=True, icon=icons.TASK_COMPLETED if prefs.date_locale == 'en_US' else icons.TASK
            )

        workflow().add_item(
            'Require explicit due keyword',
            'Requires the due keyword to avoid accidental due date extraction',
            arg='-pref explicit_keywords', valid=True, icon=icons.TASK_COMPLETED if prefs.explicit_keywords else icons.TASK
        )

        workflow().add_item(
            'Check for experimental updates to this workflow',
            'The workflow automatically checks for updates; enable this to include pre-releases',
            arg=':pref prerelease_channel', valid=True, icon=icons.TASK_COMPLETED if prefs.prerelease_channel else icons.TASK
        )

        workflow().add_item(
            'Force sync',
            'The workflow syncs automatically, but feel free to be forcible.',
            arg='-pref sync', valid=True, icon=icons.SYNC
        )

        workflow().add_item(
            'Switch theme',
            'Toggle between light and dark icons',
            arg='-pref retheme',
            valid=True,
            icon=icons.PAINTBRUSH
        )

        workflow().add_item(
            'Main menu',
            autocomplete='', icon=icons.BACK
        )