Giter VIP home page Giter VIP logo

simpletimetracker-wearos's Introduction

Simple Time Tracker

Simple app that helps track how much time you spend on all the useless activities in the world.

Get it on F-Droid Get it on Google Play Get it on GitHub

Track different activities

main_thumb

Add, change or delete activities

change_record_type_thumb change_record_type_color_thumb change_record_type_icon_thumb

View previous records

records_thumb

Add, change or delete records

change_record_thumb change_record_activity_thumb

Views statistics on different time ranges

statistics_thumb

View detailed statistics

statistics_detail1_thumb statistics_detail2_thumb

Widgets

widgets_thumb widget_universal_thumb

Notifications

notifications_types_thumb notifications_inactivity_thumb

Dark mode

darkmode1_thumb darkmode2_thumb darkmode3_thumb

WearOS

wearos_demo

Technology stack

  • Kotlin
  • Multi module
  • Single Activity
  • MVVM (Jetpack ViewModel + LiveData)
  • Jetpack Navigation
  • Jetpack Compose (WearOS)
  • Hilt
  • Room, migrations
  • Coroutines
  • Widgets
  • Notifications
  • Custom Views (Pie Chart, Bar Chart, Color Selection, Calendar)
  • Recycler, custom Adapter Delegates, DiffUtils with Payloads
  • Drag and Drop, Gesture detection
  • Gradle Kotlin DSL
  • View Binding
  • Database backup and restore, export to csv, automatic backup
  • Dark mode
  • Unit tests, UI tests
  • CI with github actions
  • Emojis with EmojiCompat

Directory structure

.
├── .github                               # CI files.
├── app                                   # Mobile app.
├── buildSrc                              # Deps and versions.
├── core                                  # Shared classes, strings.
├── data_local                            # Database.
├── domain                                # Business logic.
├── navigation                            # Navigation interfaces and screen params.
├── wear                                  # WearOS app.
├── wear_api                              # Mobile - WearOS communication
├── features
│   ├── feature_archive                   # Screen for archived data.
│   ├── feature_base_adapter              # Shared recycler adapters.
│   ├── feature_categories                # Screen for categories and tags.
│   ├── feature_change_activity_filter    # Edit activity filter screen.
│   ├── feature_change_category           # Edit category screen.
│   ├── feature_change_record             # Edit record screen.
│   ├── feature_change_record_tag         # Edit tag screen.
│   ├── feature_change_record_type        # Edit type screen.
│   ├── feature_change_running_record     # Edit timer screen.
│   ├── feature_date_edit                 # Data edit screen.
│   ├── feature_dialogs                   # Dialogs.
│   ├── feature_goals                     # Separate screen for goals.
│   ├── feature_main                      # Main screen with tabs.
│   ├── feature_notification              # Notifications.
│   ├── feature_records                   # One of main tabs, records list.
│   ├── feature_records_all               # Screen showing all records.
│   ├── feature_records_filter            # Dialog for records filters.
│   ├── feature_running_records           # One of main tabs, timers.
│   ├── feature_settings                  # One of main tabs, settings.
│   ├── feature_statistics                # One of main tabs, statistics.
│   ├── feature_statistics_detail         # Screen showing detailed statistics.
│   ├── feature_tag_selection             # Screen for selecting tags.
│   ├── feature_views                     # Custom views.
│   └── feature_widget                    # Widgets.

License

Android App

Copyright (C) 2020-2024 Anton Razinkov [email protected]

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

WearOS App

Copyright (C) 2023-2024 Joseph Hale https://jhale.dev, @kantahrek, Anton Razinkov [email protected]

This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

simpletimetracker-wearos's People

Contributors

ahmad0a avatar bahalbach avatar bandidosjr avatar cogk avatar evrenckn avatar gyrraf avatar ilyabizyaev avatar johnveness avatar kantahrek avatar kyu-suke avatar lewisleedev avatar ngocanhtve avatar poussinou avatar preethamrn avatar pyr0x1 avatar r3-da avatar rasmussehlin avatar razeeman avatar rec0de avatar thehale avatar zolax9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

simpletimetracker-wearos's Issues

Pull Tag Colors

Pull tag colors from the phone and render them on the TagScreen.

Comparable to how it's done on the ActivityScreen.

Dynamic Tag List

Currently the app hard-codes a set of tags (specifically what I used a few months ago).

We want the app to update live alongside changes to tags in Razeeman's app. See #3 for a list of strategies for accomplishing this.

Add app icon for WearOS app

Currently, the WearOS app uses the default Android icon.

We want it to install with the same icon as the phone app.

Respect setting to start an activity after choosing a single tag

Razeeman's app has a setting which enables starting an activity immediately after the first tag is selected (even if the activity has multiple tags available).

If that setting is enabled on the phone, the watch app should behave accordingly.

Some notes:

  • The user can still opt to choose "no tags" when starting the activity.
  • At the time of writing, this is the only supported behavior in the watch app. This issue thus focuses on tying that behavior to the appropriate setting from Razeeman's app instead of applying it as a global default.

Render Activity Icons

A shortcoming of the implementation for #3 is that the SVG icons for activities do not render on the WearOS app.

We'd like activity icons on the Watch to match the Phone app as closely as possible.

  • SVG Icons
  • Emojis
  • Text Icons ~ shows the first few characters. Doesn't wrap like on the phone.

Respect setting permitting multi-tasking

Razeeman's app has a setting which allows users to multi-task, i.e. have zero to multiple activities running simultaneously.

When that setting is enabled on the phone, the following behaviors are expected from the watch app:

  • Pressing a running activity on the ActivitiesScreen stops that activity, and that activity alone.
  • Pressing a stopped activity on the ActivitiesScreen starts that activity alone, leaving other running activities continuing to run.

Note that when starting an activity, the behavior must still respect the settings described in #15, #16, and #17.

Block "swiping backwards" to re-enter tag list

After starting a new activity and choosing its tag, a user can "swipe back" on the activity list to return to the previous tag list.

This happens because the navigation pushes a new navigation stack frame when returning to the activities list. Thus, the "swipe back" clears that stack frame to return to the previous tag list.

The expected behavior of the "swipe back" gesture on the activity list is that the app closes (goes back to the previous screen offered by the operating system).

I presume the solution is to clear/reset that navigation stack when moving from the TagScreen to the ActivitiesScreen.

Finish Mobile <-> WearOS Communication

This is a top-level ticket tracking progress towards full implementation of the SimpleTimeTrackerAPI on both the WearOS and Mobile apps.

Background

Communication between the WearOS app and the Mobile app occurs via an RPC Client/Server implemented using Google's MessageClient and its related APIs.

The plumbing of the communication is already complete: the wear app has an RPC client that sends messages to the phones's RPC server (implemented as a Service so it can respond even when the app is in the background or the phone is sleeping).

sequenceDiagram
    actor User
    
    box green WearOS
    participant UI (Wear)
    participant WearRPCClient
    participant Messenger
    end

    box blue Phone
    participant WearService
    participant WearRPCServer
    participant DomainAPI
    end

    User->>UI (Wear): Interact with Wear app
    UI (Wear)->>WearRPCClient: Request needed data
    WearRPCClient->>WearRPCClient: Serialize message to BytesArray
    WearRPCClient->>Messenger: Request message delivery
    Messenger->>Messenger: Find nearest node
    Messenger->>WearService: Send message to phone
    WearService->>WearService: Wake up from sleep/background
    WearService->>WearRPCServer: Delegate message to RPC Server
    WearRPCServer->>WearRPCServer: Parse the message
    WearRPCServer->>DomainAPI: Request needed data
    DomainAPI->>DomainAPI: Query/update the Database
    DomainAPI->>WearRPCServer: Return data from database
    WearRPCServer->>WearService: Serialize response to BytesArray
    WearService->>Messenger: Return response
    Messenger->>Messenger: Run validation checks/error handling
    Messenger->>WearRPCClient: Forward response
    WearRPCClient->>WearRPCClient: Parse response
    WearRPCClient->>UI (Wear): Return requested data
    UI (Wear)->>User: Render UI update

Both the WearRPCClient and the DomainAPI implement the SimpleTimeTrackerAPI interface which defines all the methods believed to be necessary for the WearOS MVP.

Remaining Work

The following list of tickets track each method in WearRPCClient and DomainAPI not yet implemented. Once all the following are complete, this ticket can be closed as complete.

WearOS app

  • Implement WearRPCClient.ping
  • Implement WearRPCClient.queryActivities
  • Implement WearRPCClient.queryCurrentActivities
  • Implement WearRPCClient.setCurrentActivities
  • Implement WearRPCClient.queryTagsForActivity
  • Implement WearRPCClient.querySettings

Mobile app

  • Implement WearRPCServer.onRequest
  • Implement WearRPCServer.onPing
  • Implement WearRPCServer.onQueryActivities
  • Implement WearRPCServer.onQueryCurrentActivities
  • Implement WearRPCServer.onSetCurrentActivities
  • Implement WearRPCServer.onQueryTagsForActivity
  • Implement WearRPCServer.onQuerySettings
  • Implement DomainAPI.ping
  • Implement DomainAPI.queryActivities
  • Implement DomainAPI.queryCurrentActivities
  • Implement DomainAPI.setCurrentActivities
  • Implement DomainAPI.queryTagsForActivity
  • Implement DomainAPI.querySettings

Clean up README

  • Remove my custom header stuff
  • Add screenshots for WearOS
  • Add a licensing note regarding the MPL license for the WearOS code

Dynamic Activity List

Currently, the app hard-codes the list -- specifically what I used several months ago --, meaning any customization requires a complete re-build/install of the app.

Good: Allow the companion app to add/remove activities visible to the watch
- Pros: No need to modify Razeeman's app.
- Cons: Users would need to manually mirror activities/tags between the WearOS version and the official app.

Better: Add an Intent API to Razeeman's app for querying all available activities (+ colors)
- Pros: Keeps the watch's set of activities and tags automatically in sync with the official app
- Cons: Requires modifying Razeeman's app.

Best: Integrate the WearOS app directly into Razeeman's app, and build a MessageClient there instead of an Intent API

  • Pros: The best long-term experience for developers and users.
  • Cons: Requires modifying Razeeman's app. Possibly the hardest option on the list.

Remaining steps after 9614a5c for a full MVP:

  • Add support on Wear for all icons supported by mobile (tracked by #11)

Work on the actual functionality for tapping an activity chip and having it start the activity on the phone will be tracked in #5

Unable to start an activity which has zero tags

Since the TagScreen only runs the logic to start an activity when a tag chip is pressed, activities with no tags cannot be started.

If an activity has no tags, then it should start automatically.

In the watch app, show the current activity(ies) and duration

Will increase users' confidence that their activity changes have been recorded as expected.

Will require adding an Intent API to Razeeman's app to query the current activities (e.g. ReadRunningRecords or ReadActiveRecords based on his preferred nomenclature in the app).

Will also require adding an Intent API to query user preferences, particularly multitasking (e.g. ReadPreferences)

UPDATE: With the new communication layer in place (see #8), all that's needed for the Wear app to access the current activities and their durations is to implement DomainAPI.queryCurrentActivities and WearRPCClient.queryCurrentActivities. From there, the UI can be designed as desired.

In the watch app, choose the activity separately from tags

Currently, the watch shows a list of activities and tag pairs. That works fine for the subset of users who only ever attach a maximum of one tag to an activity, but many users (myself included) often want to attach more than one tag to an activity.

The best solution here would be to split the single list of activity/tag pairs in two to better mirror the experience in the Android app. The user would first see the list of activities. After selecting one, the user would be shown a checklist of possible tags. After choosing zero or more tags, the user could "save" his/her choice and the selected activity/tag(s) would be sent to the Android app like normal.

NOTE: Not yet in scope is supporting simultaneous activities ("multitasking" as Razeeman calls it).

Start an activity without choosing a tag

To start an activity, currently one MUST choose a tag. That's not a requirement on the phone app.

When an activity has one or more tags available as options, starting the activity with zero associated tags should still be possible.

This feature request is subtly different from the bug reported in #12. That bug applies when zero tags are available for association with the chosen activity. This feature request is for the ability to elect to choose zero out of a set of available tags when starting an activity.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.