Code Monkey home page Code Monkey logo

kiroku's Introduction

Download the app

image

Table of Contents

For developers

  • This section is intended for developers only and will later be moved into the Jekyll documentation.

On the platform choice

  • We highly recommend you use Mac for working on this project. Given its compatibility with both Android and iOS, it is an ideal platform for developing a unified and efficient working environment. Fastlane, Bun, and other tools are readily available for Mac, allowing you to ease up your workflow significantly.
  • If you can not, or do not want to develop on MacOS, you may need to substitute Bun with other package managers, such as npm, and some features of the application may be unavailable to you.

Setting up the local environment

  • We use Bun for package managing. This experimental approach should come at the added benefit of allowing you to spend less time worrying about packages, and more time coding. Install Bun using

    curl -fsSL https://bun.sh/install | bash
  • Most of the local environment setup right after cloning the repository can be handled with the following commands.

    bundle update
    bun i
    bun -g i firebase-tools
    cd ios
    pod install

Updating the application version

  • In the future, the application versioning will be rewritten into a github action. As of now, you can update the version (local, and for all platforms) using

    bun run bump:<SEMVER_LEVEL>

    where <SEMVER_LEVEL> can be one of the following:

    • BUILD: Increments the build version.
    • PATCH: Increments the patch version, where only small changes are introduced.
    • MINOR: Increments the minor version, where no API breakiing changes are introduced.
    • MAJOR: Increments the major version, where major, API breaking changes are introduced.
  • The command creates a new commit in the current branch with the updated version. You can then push to origin these changes as you see fit.

  • The command should always be ran on the staging branch and from the project root. No version updates should happen on the master branch, nor in smaller branches. This should help keep one source of truth. When merging to the staging branch, never accept changes from the incoming branch.

  • We use semantic versioning.

Building for Android

  • Create a local.properties file in the android folder and put the following inside:

    sdk.dir = /Users/USERNAME/Library/Android/sdk

    where you replace USERNAME with your username. On windows, adjust the path to point to your Android SDK folder.

  • Make sure to add this path to the ANDROID_HOME by running

    export ANDROID_HOME = /Users/USERNAME/Library/Android/sdk

    If this variable is not set, you might be running into the Error: Command failed with EN0ENT bug upon trying to connect to an emulator.

  • Build the .APK file using bun run build:android (calls fastlane android build). To bundle the build for Google Play release, run fastlane android beta.

  • Running bun run build:android may fail with insufficient permissions to open the gradlew file. In that case, run

    chmod +x ./android/gradlew

    to make the file readable.

Formatting

  • For typescript and javascript files, we use Prettier
  • For bash scripts, we use shell-format

Managing ruby versions

  • We officially use Ruby version 2.6.10. To read about ruby version configuration see this link.

Platform-Specific File Extensions

In most cases, the code written for this repo should be platform-independent. In such cases, each module should have a single file, index.js, which defines the module's exports. There are, however, some cases in which a feature is intrinsically tied to the underlying platform. In such cases, the following file extensions can be used to export platform-specific code from a module:

  • Mobile => index.native.js
  • iOS Native App/Android Native App => index.ios.js/index.android.js
  • Web => index.website.js
  • Desktop => index.desktop.js

Note that index.js should be the default and only platform-specific implementations should be done in their respective files. i.e: If you have mobile-specific implementation in index.native.js, then the desktop/web implementation can be contained in a shared index.js.

index.ios.js and index.android.js are used when the app is running natively on respective platforms. These files are not used when users access the app through mobile browsers, but index.website.js is used instead. index.native.js are for both iOS and Android native apps. index.native.js should not be included in the same module as index.ios.js or index.android.js.

Working with Firebase

  • Firebase CLI is necessary for any Firebase tests/emulators to run correctly. In order to set up your local environment, run these commands first

    bun -g i firebase
    firebase login
    firebase init
    

Writing Firebase rules

Overview

  • When setting the Firebase rules, here are a several useful behavior patterns to keep in mind:

    • .read and .write rules cascade in the following way:

      1. Rules get evaluated based on the node depth until the operation ultimately fails/succeeds.
      2. Allowing an operation in a higher node means that similar operations ran on any lower node will succeed.
      3. Targetting a lower node may lead to an allow as long as the final node's rule succeeds. This is despite any rules failing in higher nodes.
      4. If the node into which is written does not have any write/read rules, the rules of higher order nodes will take effect instead, based on the rules described above.
    • To demonstrate the two above-principles, consider this example:

      "higher_node": {
          ".write": true,
          "lower_node": {
              ".write: false"
          }
      }
      
      • Writing to the higher node: succeeds
      • Writing to the lower node: succeeds
      • Explanation: Attempting to write to the lower node will succeed, as a higher node is setting the write rule to true. The lower node`s rule is considered, but the higher order rule's allow operation takes precedence. Next, writing to the higher node will succeed too, regardless of the rules in the lower node (these are not considered).
    • Next, take a look at this example:

      "higher_node": {
          ".write": false,
          "lower_node": {
              ".write: true"
          }
      }
      
      • Writing to the higher node: fails
      • Writing to the lower node: succeeds
      • Explanation: When targetting the higher node, the write deny rule means the operation will fail. The rule in the lower node is not taken into consideration (regardless of the outcome). When writing to the lower node, the operation will succeed, as despite the higher node denial, it holds that denial in higher nodes
    • Under this setup, the database will allow writes into the lower order node even though you are explicitly trying to forbid it by setting the rules to false there. To forbid writes into the lower order node, make sure to address the higher order rules first.

  • When dealing with .validate, the behavior is a little different. The validation rules apply only to the node for which they are written. In other words, they do not cascade. If you, for example, want all members of a node to be either null, or a certain string, you must set this value for all nodes for which this should be relevant. Simply setting this to a higher order node will not suffice.

Strategy

  • For read/write, define restrictive rules at higher nodes, and allow broader access at concrete nodes. For example:

    "users": {
        "$uid": {
            ".write": "auth != null && $uid ==== auth.uid",
            "friend_requests": {
                "$friend_request_id": {
                    ".write": "auth != null"
                }
            }
        }
    }
    
    • This will allow only the user to write to their data, except for the friend_requests node, in which other user will be able to write data too.
    • Note that the write rules from the $uid node also cascade to the friend_requests node, protecting the latter from other users making direct modifications to it as a whole. Consequently, the only allowed write operations on this structure for other users will be to append/delete data to the friend_requests node.
    • If a user deletes the last of the data in that node, Firebase will automatically delete it. Thus, this operation will be recognized as a Firebase deletion, and will not fall under the defined rules. Vice versa, create it if it is the first record in that node. There is no need to write to the node reference itself.
  • For a more fine-grained managemene of the type of data that can be written into a node, use .validate. In the previous example:

    "users": {
        "$uid": {
            ".write": "auth != null && $uid ==== auth.uid",
            "friend_requests": {
                "$friend_request_id": {
                    ".validate": "(($uid === auth.uid && newData.val() === 'sent') || ($request_id === auth.uid && newData.val() === 'received') || newData.val() === null) && $uid != $request_id",
                    ".write": "auth != null"
                }
            }
        }
    }
    
    • This new rule ensures that the user can either add a sent request to their own node, add received request to other user's node, or delete a request. They also can not send a friend request to themselves.
    • The new, more granular logic, allows us to specify the type of data that is being written into the database.
  • It might seem tricky to figure out whether to write a rule into .validate or .read/.write. As a rule of thumb, if the rule targets who is requesting the operation, .read/.write might be suitable. If specifying the type of data is what you are after, .validate should do the trick. More than anything, however, keep the cascading nature of each of these rule types in mind, and use it to your advantage to avoid redundancy, while keeping the rules clear and intuitive.

Migrating the database

The database migration process is handled in a rather manual fashion. As of now, the procedure is as follows:

  1. Make sure your _dev folder contains the folder migrations. This folder should in turn contain folders input and output.
  2. Inside the input folder, place the database you want to migrate (do not rename it from the Firebase import).
  3. Call the relevant migration script (located inside the _dev/database/migration-scripts folder) from the _dev/main.tsx file. You can run this file using either bun, or ts-node.
  4. The output will be located in the _dev/migrations/output folder. From there, you can update the relevant database.

Database maintenance

You can schedule database maintenance directly from the command line using bun run maintenance:schedule, provided you have the corresponding admin SDK. After the maintenance is over, you will have to cancel it through running bun run maintenance:cancel. For more detail, see the following sections.

Scheduling maintenance

  1. In .env, set the environment of the database you want to schedule the maintenance for.

  2. Place the admin SDK file of this database into the project root, and make sure the admin SDK paths in the .env file are configured correctly to point to this file.

  3. From the project root, run

    bun run maintenance:schedule

    From there, follow the on-screen instructions.

Cancelling maintenance

  1. Follow steps 1-2 from the previous section.

  2. From the project root, run

    bun run maintenance:cancel

    and follow the on-screen instructions.

Understanding the maintenance mechanism

  • Scheduling a maintenance will update the config/maintenance node of the database. Namely, the maintenance_mode will be set to true, while the start and end time will be set to your desired values. As long as the maintenance_mode flag is on, all users will be shown a maintenance screen upon opening the application.
  • There is no in-built check to make sure the maintenance time is over. As such, the start/end times are purely of informational character. This is to allow the developers more flexibility. Consequently, after the actual maintenance is over and the app is ready to be made available to users, simply cancel the maintenance using the instructions in the Cancelling maintenance section. This will set the maintenance_mode to false, allowing application access to users.

kiroku's People

Contributors

petrcala avatar kirokuadmin avatar

Watchers

 avatar

kiroku's Issues

Navigation speed

Refactorization of the navigation system caused a massive drop is navigation speed. Identify the cause of this problem and fix it

DrinkingSessionData not resetting

The drinkingSessionData on main screen does not get reset upon deleting the drinking sesssiom data, if the deleted sessiom is the only one in the database

Disable flipper in Podfile

The flipper package is causing problems in package installation. Disable the packaged at the top of the file by setting flipperconfig to disabled at all time

App crashing upon logging out

The app crashes sometimes when logging out

Metadata

Versions

  • Version 0.1.0

List of known affected devices

  • Device: iPhone 11 Pro
  • OS: iOS 17

-Device: iPhone 14

  • OS: iPhone 17.1.2

Refactor screen handling

Screens

  • There should be a single file src/SCREENS.ts that should contain information (names) of all screens. As such, navigating to screens, their types, etc. should be centralized, and error-proof.
  • Change the screen naming to "Screen_Group_Screen_Name"

Terms and agreements, data handling,...

Design a proper, clever, and all-encompassing layout for the terms and agreements, policies of data handling, etc. These should comply with all modern standards and not violate any rules nor policies etc.

User preferences into callback

Transform the preferences that are being passed down to the preferences screen so that they can be updated on the main menu screen using a callback function (see numeric slider)

Navigation package dependencies

Validate when building iOS, that the correct dependencies are installed for the navigation to run - see here.

Possibly
cd ios
pod install
cd ..
could be necessary.

Unable to start a new drinking session

Description

  • Some android users experience not being able to start a new drinking session through the main screen "Start new session" button

Version

  • 0.2.7

List of affected devices

  • OS: Android

Add groups

Overview

Users should in the future have the option to create and join groups. These would be the main way to compete in monthly rankings, and to evaluate performance and award badges.

ESLint setup finish

ESLint setup finish

  • Finish setting up the .eslint configuration
  • Clean up the project based on this configuration

Group emails

Add a functionality that will allow the admin to send out group emails to all users of the application. These should adhere to GDPR regulations, etc.

Session edit failed

When saving a session edit, the save can fail when a note is empty (the application recognizes this as undefined) (version 0.2.0). Possibly change the save session so that all properties are set to something, be it most likely empty arrays.

Things to do upon launching version >=0.2.0

  • Migrate all user data using refactorUsersData - ensures there are no users with the old user data structure
  • Migrate all user preferences data using refactorPreferencesData - ensures there are no users with the old preferences data structure

Add a list of known bugs

Until the major version is released, add a window listing all major bugs that the user should be aware of.

Day overview not updating

After finishing a session edit, the day overview screen does not get updated with these information (version 0.2.0)

This month drinking session functions refactorization

Rewrite the data handling functions that focus on getting this month ... (used in main screen, day overview screen) to accept a date object. Rewrite the tests. Possibly even move the functions into a separate file.

newArchEnabled build bug

The application can not be built as of the last 0.2.0 commit 9651457.

Perhaps this is due to the newArchEnabled setting in gradle.properties?

iOS incorrect email field suggestion

On iOS, when creating a new user, the second field (currently username) is suggesting an e-mail, wheres the first field (currently email) should have this functionality

Documentation build

Verify that any user will be able to build the developer documentation using Sphinx right off the bat without any necessary installations.

Session note and feedback writing buttons visibility

When writing any text, such as the sesison note, or the user feedback, the buttons that allow this to be saved should always be visible when writing. Clicking back feels less intuitive and should be discouraged.

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.