Giter VIP home page Giter VIP logo

xebow's Introduction

Overview

Xebow is a nerves-based firmware for the Keybow keypad.

This project is in early development. Features and the API may be subject to change.

Resources:

  • Join the #nerves-keyboard channel on the elixir-lang Slack to chat with us and keep up on the latest developments.
  • Visit the wiki to see past meeting notes and other content.
  • Planning meetings are open to all. Feel free to join if you would like to familiarize yourself with the internals of Xebow or would like to find a place to help out. The schedule is pinned in the Slack channel.
  • Wireframes are available on Figma.

Initial Setup

Checking out the Project

$ git clone [email protected]:ElixirSeattle/xebow.git
$ cd xebow

SSH Access (optional)

If you would like to flash firmware to the MicroSD card without having to remove it from the keybow each time, you will need to set up SSH access. This also provides access to a running iex shell for running commands directly on the device.

If your SSH public key is not in your home directory's .ssh/ directory with one of the following names, then you can specify the path to your public key by setting the NERVES_SSH_PUB_KEY environment variable:

  • id_rsa.pub
  • id_ecdsa.pub
  • id_ed25519.pub

Building the Firmware

If you have not used nerves to build firmware before, you may need to install several dependencies. See the installation guide if this is your first time using nerves.

The keybow uses a Raspberry Pi Zero WH, so the target would be rpi0. However, to better support all the keybow features that xebow uses, a custom target has been setup called keybow that you will need to use instead. To build and burn the firmware:

$ export MIX_TARGET=keybow
$ mix deps.get
$ mix firmware

Writing the Firmware to the MicroSD Card

Insert the MicroSD card into an card reader attached to your computer and then run:

$ mix firmware.burn

The mix firmware.burn command will try to detect your MicroSD card and offer to write the data to the card. IMPORTANT: Triple-check that the device it plans to write to is the MicroSD Card, or you could permanently delete data on another device.

Booting the Keybow

Remove the MicroSD card and insert it into the keybow. Plug the keybow into the computer and wait for it to boot. Once booted, the keypad should begin cycling all keys through a rainbow of colors.

Updating the firmware

The firmware can be updated while the Keybow is attached to your computer as long as the Xebow firmware is running on it.

Build the firmware and upload it via SSH by running:

$ mix firmware.upload

If you would like to perform these steps individually, use mix firmware and mix upload.

Notes

  • The upload needs to be run on a computer with the same SSH public key that was used when burning the SD card or else it won't be able to connect to the Keybow.
  • If the xebow.local hostname can't be resolved, try unplugging the Keybow from the USB port, wait for the computer's USB disconnect notification, then plug the Keybow back in and try again after it's booted back up.

Web Interface

The following instructions are for running the Xebow web interface on your computer for a faster development cycle.

If this is your first time running the web interface, set up the web app with:

$ mix setup

Start the web interface, which will be available at http://localhost:4000:

$ mix phx.server

Keyboard Layout

The xebow firmware sets up the keybow as a 10-key numpad. Turn the keypad so the flashing LEDs are on the left of each key and the USB cord is facing right. In this position, the keypad has the following layout:

+-----+-----+-----+
|  7  |  8  |  9  |
+-----+-----+-----+
|  4  |  5  |  6  |
+-----+-----+-----+
|  1  |  2  |  3  |
+-----+-----+-----+
|  0  | L-1 | L-2 |
+-----+-----+-----+

The L-1 and L-2 keys activate different "layers" of the keypad, which allows mapping additional commands to each key. For example, holding L-2 and hitting 7 will trigger a command to flash the keypad red.

Keyboard Shortcuts

  • L-1 + 9: volume up
  • L-1 + 6: volume down
  • L-1 + 8: mute
  • L-2 + 7: flash keypad red
  • L-2 + 9: flash keypad green
  • L-2 + 4: previous animation
  • L-2 + 6: next animation

xebow's People

Contributors

amclain avatar dependabot[bot] avatar dhedlund avatar doughsay avatar rraub avatar vanvoljg avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xebow's Issues

Refactor: Cycling to a previous or next animation is the application's responsibility

The Engine currently contains functionality for cycling to the previous_animation and next_animation (shown below). However, in the 2020-06-23 meeting we realized these are responsibilities of the application rather than the rendering engine. Therefore, we should move this code out of Engine, leaving the engine with the play_animation function for the application to tell the engine which animation should currently be playing.

https://github.com/ElixirSeattle/xebow/blob/e5589fdec01278b23f043fea198c164ce97eed01/lib/xebow/engine.ex#L31-L45

Replace userspace generated USB devices through ConfigFS with something more robust and portable

Nerves out of the box uses a built-in kernel module CONFIG_USB_ETH=y. This is widely compatible across operating systems, but lacks the HID device we need for a keyboard.

The conventional wisdom to create composite USB devices is to use Linux's ConfigFS, which is what xebow does. (It creates a composite NCM Ethernet + RNDIS Ethernet + HID device, using ConfigFS: https://github.com/ElixirSeattle/xebow/blob/master/lib/xebow/hid_gadget.ex). The problem seems to be that we can't create an Ethernet device through ConfigFS that mimics the portability and robustness of the built-in kernel module... the NCM + RNDIS devices are a hack (one works on windows (RNDIS), the other works on linux and macOS (NCM)).

We need to either try harder to mimic the same behavior as the built-in module through configFS, or scrap configFS altogether, and maybe write our own composite HID + Ethernet kernel module based on the one Nerves uses out of the box.

I consider this problem "very hard".

Style the select element options list

We would like to restyle the options list for the select element away from the browser default and to a style that matches the Xebow look and feel. Tailwind claims this requires a considerable amount of JavaScript, so waiting for their library seems reasonable unless someone feels passionate about writing this custom code.

Custom select controls like this require a considerable amount of JS to implement from scratch. We're planning to build some low-level libraries to make this easier with popular frameworks like React, Vue, and even Alpine.js in the near future, but in the mean time we recommend these reference guides when building your implementation:

https://www.w3.org/TR/wai-aria-practices/#Listbox
https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html

link

Design

Figma

image

Live view `Option` fields sometimes show incorrect values

In the live view, there are instances where an Option field type will not show the correct value for an animation.

This happens because the live view doesn't check what the current value for an option is when building the <select> option list.

Minimum reproduction steps:

  1. Delete settings directory: rm -rf priv/settings
  2. Run locally: iex -S mix phx.server
  3. Open web interface, "Next Animation" to Hue Wave, and change the direction to "Up"
  4. Menu -> Animations, turn off any of the animations except Hue Wave
  5. Menu -> Dashboard, switch back to Hue Wave, and observe that Direction shows "Right", but the animation still plays as if it were "Up".

Tutorial: Handling key events

Note: The AFK API may change.

We would like to have a tutorial for Xebow integrators to be able to learn how to listen and respond to key events (press/release) in their applications. Part of this tutorial could include an explanation of keys.ex.

Color picker

We would like to have a color picker widget in the web UI for users to be able to pick the colors they want to set LEDs to.

We could start out with a basic interface that supports HSV & RGB (and maybe the hex value) and lets a user pick a color by either adjusting the sliders or typing in numbers for each property's value. A square could show a preview of the color to the user. We could use the existing dependency chameleon to help with this task.

Mockup:

image

Refactor RGBMatrix.Animation submodules

The animations have multiple places where they need to be touched up.

SolidReactive module has three TODOs, one FIXME, and one Credo-suggested refactor to reduce nesting depth:

SolidColor has a TODO:

Breathing:

HueWave:

Cycling animations when none are available causes a crash

Description

If all of the animations are disabled, attempting to cycle to the next/previous animation causes a crash. Based on the error message, it appears that the config is trying to be retrieved for a non-existent animation.

** (UndefinedFunctionError) function nil.config/0 is undefined
    nil.config()
    (xebow 0.1.0) lib/rgb_matrix/animation.ex:105: RGBMatrix.Animation.get_config/1

Expected behavior

Nothing happens when attempting to cycle the animation (no-op).

Steps to reproduce

Disable all active animations on the animations page.

image

Navigate back to the dashboard and cycle to the next or previous animation.

image

The following error is printed in the console.

[error] GenServer RGBMatrix.Engine terminating
** (UndefinedFunctionError) function nil.config/0 is undefined
    nil.config()
    (xebow 0.1.0) lib/rgb_matrix/animation.ex:105: RGBMatrix.Animation.get_config/1
    (xebow 0.1.0) lib/rgb_matrix/engine.ex:233: RGBMatrix.Engine.inform_configurables/1
    (xebow 0.1.0) lib/rgb_matrix/engine.ex:182: RGBMatrix.Engine.handle_cast/2
    (stdlib 3.13) gen_server.erl:680: :gen_server.try_dispatch/4
    (stdlib 3.13) gen_server.erl:756: :gen_server.handle_msg/6
    (stdlib 3.13) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:set_animation, nil}}
State: %RGBMatrix.Engine.State{animation: %RGBMatrix.Animation{config:
%RGBMatrix.Animation.SolidReactive.Config{direction: :random, distance: 180,
speed: 4}, state: %RGBMatrix.Animation.SolidReactive.State{color:
%Chameleon.HSV{h: 190, s: 100, v: 100}, first_render: false, hits: %{}, leds:
[%Layout.LED{id: :l001, x: 0, y: 0}, %Layout.LED{id: :l002, x: 1, y: 0},
%Layout.LED{id: :l003, x: 2, y: 0}, %Layout.LED{id: :l004, x: 0, y: 1},
%Layout.LED{id: :l005, x: 1, y: 1}, %Layout.LED{id: :l006, x: 2, y: 1},
%Layout.LED{id: :l007, x: 0, y: 2}, %Layout.LED{id: :l008, x: 1, y: 2},
%Layout.LED{id: :l009, x: 2, y: 2}, %Layout.LED{id: :l010, x: 0, y: 3},
%Layout.LED{id: :l011, x: 1, y: 3}, %Layout.LED{id: :l012, x: 2, y: 3}],
paused: true, tick: 0}, type: RGBMatrix.Animation.SolidReactive}, configurables:
#MapSet<[#Function<5.66497960/1 in XebowWeb.MatrixLive.register_with_engine!/0>]>,
last_frame: %{l001: %Chameleon.HSV{h: 190, s: 100, v: 100},
l002: %Chameleon.HSV{h: 190, s: 100, v: 100}, l003: %Chameleon.HSV{h: 190, s: 100, v: 100},
l004: %Chameleon.HSV{h: 190, s: 100, v: 100}, l005: %Chameleon.HSV{h: 190, s: 100, v: 100},
l006: %Chameleon.HSV{h: 190, s: 100, v: 100}, l007: %Chameleon.HSV{h: 190, s: 100, v: 100},
l008: %Chameleon.HSV{h: 190, s: 100, v: 100}, l009: %Chameleon.HSV{h: 190, s: 100, v: 100},
l010: %Chameleon.HSV{h: 190, s: 100, v: 100}, l011: %Chameleon.HSV{h: 190, s: 100, v: 100},
l012: %Chameleon.HSV{h: 190, s: 100, v: 100}}, leds: [%Layout.LED{id: :l001, x: 0, y: 0},
%Layout.LED{id: :l002, x: 1, y: 0}, %Layout.LED{id: :l003, x: 2, y: 0},
%Layout.LED{id: :l004, x: 0, y: 1}, %Layout.LED{id: :l005, x: 1, y: 1},
%Layout.LED{id: :l006, x: 2, y: 1}, %Layout.LED{id: :l007, x: 0, y: 2},
%Layout.LED{id: :l008, x: 1, y: 2}, %Layout.LED{id: :l009, x: 2, y: 2},
%Layout.LED{id: :l010, x: 0, y: 3}, %Layout.LED{id: :l011, x: 1, y: 3},
%Layout.LED{id: :l012, x: 2, y: 3}], paintables:
#MapSet<[#Function<4.66497960/1 in XebowWeb.MatrixLive.register_with_engine!/0>]>,
timer: nil}

Refactor config value casting

Originally I had the phoenix live-view responsible for casting values coming from the client, strictly requiring that all values were correct before being passed in to Config.update. This is obviously not that great... it would be much nicer if Config.update returned either :ok, or {:error, :cast_error} or something like that. This would be a nicer developer experience. As of right now, it will crash with a pattern match error, which is not ideal.

UI: System page - USB Ethernet mode

We would like to add the ability for a user to change the mode of the USB Ethernet endpoint that Xebow exposes to the host.

Xebow currently exposes two Ethernet endpoints, RNDIS and NCM. This is because neither driver is fully compatible with all operating systems (see #91). If Xebow is only being connected to a single operating system type, a user may want to disable the other unused Ethernet endpoint which will show up as an invalid device, and may also be periodically rediscovered by the O/S and cause notifications to pop up.

Note that disabling one type of Ethernet endpoint may result in the device being unusable if it is connected to another type of operating system. Due to this, we also need to expose a recovery mechanism if the user encounters this state.

Acceptance Criteria

  • On the settings page, allow the user to select between the following USB Ethernet modes:
    • Auto - Both RNDIS and NCM endpoints are available as connection options.
      • It is OK for one of these endpoints to be disabled after the other connects successfully, as long as they both become available if neither has a connection (eliminates the need for the network bridge).
    • RNDIS - Only the RNDIS endpoint is active.
    • NCM - Only the NCM endpoint is active.
  • The user can hold a key sequence on device boot to change this setting without the web UI (recovery mechanism).
    • Holding keys 1 & 2 changes the setting to auto.

Design

https://www.figma.com/file/RMYWHeXJoDErWii1jm8C7k/Xebow?node-id=45%3A44

System3

Tutorial: Writing an animation

Depends on #43.

We would like to have documentation that shows a new animation designer how to write an animation for Xebow.

This may include topics like:

  • Where the built-in animation files are stored (here)
  • How to implement (use) Animation
  • Properties in %Animation{} that are available to an animation designer, including how to use opaque state
  • How to use the field macro
  • Understanding the layout of pixels (#43)
  • Any important details for an animation designer about how Engine renders animations

Engine: Play multiple animations simultaneously

We would like Engine to be able to play multiple animations at the same time, layering them on top of each other. Animations may either stop naturally after they have reached their number of loops played, or forcefully by instructing the engine to stop an animation that is currently in progress. The latter is especially useful for infinitely running animations.

Provide an application-level method of controlling the animation

Right now, there are no friendly ways to control the animation. There's no standardized means of telling the application to play the next/previous animation, or to change the animation's configuration.

This is especially apparent in lib/xebow_web/live/matrix_live.ex on L71, where there's logic for switching animations duplicated between the live view module and lib/xebow/keyboard.ex.

We'll need to figure out a way to do this. I'm pretty sure it'll involve some refactoring, and will likely touch a couple other issues.

Design: Layouts

As discussed in the 2020-06-23 meeting, we need to design a system to lay out pixels that don't conform to a perfect grid (like the Keybow does). We need to be able to accommodate the zig-zag layout of keys and pixels like on a full size keyboard.

Keybow's grid:

image

Zig-zag of a full size keyboard:

image

Unit testing

@doughsay & @dhedlund: Considering this project doesn't have unit tests yet, how would you feel if I implemented ESpec and configured CI? I've enjoyed using this library on other projects, and its mocks are a nice way to work around physical hardware components that aren't available during the CI run. I've also found the ESpec style of testing (inspired by RSpec) pleasant to read as well, but I realize that's subjective.

What are your thoughts?

Question: Target name

Related: #9
Related: 96c4fa8#diff-6023be6004fce4718dad3dafb576d258L6

@doughsay I noticed after PR #9 was merged the hardware target name was changed from keybow to kebow (without the y). Just want to point out that Keybow, the product, does have a y in it. Or are you going for this Kebow? 😜

It just threw me off when building the firmware, so thought I'd point it out. Am I missing something about why the name ended up the way it is now?

Standardize typespec definitions

Currently, the typespecs are not consistent with each other. Sometimes they're declared with a parameter name, sometimes just the type. We should pick one style and try to stick to it, and probably before there are a bunch of people writing code for this. It will help lower the barrier to entry for newcomers.

For instance, I find it much more readable to have literal notation whenever possible. For example, βœ”οΈ[any()] instead of ❌list(any()), or βœ”οΈ{atom(), binary()} instead of ❌tuple(atom(), binary()), except for when the functional version is more readable or conveys better meaning, like βœ”οΈmap() instead of ❌%{optional(any) => any}. I also go for functional types over bare names (:heavy_check_mark:any() vs ❌any). (This last point is just me, so if anybody thinks it's extra visual noise, I'm just fine with bare names.)

Parameterized types should be reserved for when they add to typespec clarity, like when there are multiple identical types or when the return type directly uses a given parameter. Honestly, I like having lots of typespecs, so the case of multiple identical types should be abstracted to named types. (E.g. @spec foo(integer(), integer(), integer()) ➑️ @spec foo(hours(), minutes(), seconds()) or similar, where hours(), minutes(), and seconds() are defined types of integer().)

I like the way ExDoc styles the types, and the way the Erlang docs do their specs (usually). It's highly legible. If we followed mostly the same style, then it would make it a lot easier to jump from documentation to code. This is personal preference and I'm open to any other style, as long as it's fairly consistent. AFAIK, ExDoc normalizes things when it creates the docs, so the published versions are good, but consistency is nice for people editing and reading the code, too.

Key presses are occasionally triggered twice

After pressing arbitrary keys for a while, every now and then one of the key presses ends up triggering twice. It doesn't matter if the keys are pressed fast or slow, and I have also tried varying the timing between different key presses. It feels like the issue happens more often after a small pause, but that may just be coincidence. The first few occurrences in the sequence in the screenshot seem to happen just after 50 characters, but that may also be coincidence. In the 123, 456, 789 sequence it feels like 1, 7, 5 trigger the most often. I have tried combinations of keys that are not in that group, like 2, 6, 8, and see the same issue of keys triggering twice. I have also tried the keybow on a couple different surfaces to try to eliminate mechanical bouncing of the keys if that was potentially an issue.

image

Is anyone else able to reproduce this?

UI: Key bindings page

We would like to add a page for a user to be able to choose which functionality to bind to which keys. We can start out by getting the list of scan codes from AFK and displaying them in a list for the user to select from.

This is the first iteration of this design and will be expanded on in the future.

Acceptance Criteria

  • Layers can be added and removed.
  • (Optional) Layers can be renamed.
  • A representation of the keyboard shows the mapped keys.
  • Selecting a layer shows the key mapping for that layer.
  • The user can select a key on the keyboard, and then select the AFK scan code from a list. The code will then be mapped to the key.
  • (Optional) A search box narrows down the list of codes.
    • The text in the search box can be cleared by clicking an icon next to it.

Any optional items that are deferred should be tracked in a new ticket.

Design

https://www.figma.com/file/RMYWHeXJoDErWii1jm8C7k/Xebow?node-id=59%3A82

Key Bindings

image

Refactor: Coordinate system

Depends on #43.

As mentioned in the 2020-06-23 meeting, the Keybow's physical pixels are rendered based on a position-dependent list, @pixels, in utils.ex. In this list the elements have to be in the same order that the pixels are arranged on the Keybow on the SPI bus. We would like hardware layer that controls the pixels (RGBMatrix) to be responsible for translating the pixels in a Frame to the correct physical representation.

TBD: The strategy we choose to refactor this will most likely be dependent on how we decide to design pixel layouts in #43.

Re-arrange the keyboard layout so that the keys follow natural X/Y grid coordinates rather then the keyboaor hardware order

The physical keys are given IDs in the code that both AFK and RGBMatrix are (or will be) using. The IDs are atoms like :k001, :k002, etc.

The keys are currently arranged like this:

+-----+-----+-----+
|  1  |  5  |  9  |
+-----+-----+-----+
|  2  |  6  |  10 |
+-----+-----+-----+
|  3  |  7  |  11 |
+-----+-----+-----+
|  4  |  8  |  12 |
+-----+-----+-----+

whereas they should be arranged like this:

+-----+-----+-----+
|  1  |  2  |  3  |
+-----+-----+-----+
|  4  |  5  |  6  |
+-----+-----+-----+
|  7  |  8  |  9  |
+-----+-----+-----+
|  10 |  11 |  12 |
+-----+-----+-----+

This follows the conventions of the wider mechanical keyboarding community better and removes keybow specific hardware coupling.

NPM asset installation is skipped when building firmware

If a user bypasses the mix setup step because they don't need to run the web UI locally, the workflow to burn the firmware does not include the npm install step. This results in the UI not rendering correctly when hosted from the hardware due to the missing assets.

Update to Raspberry Pi Nerves system 2.0.0

A new major release of nerves_system_rpi0 is on the way and is currently in rc0. Adopting this release will require a small change to validating the firmware. For Xebow, we should be ok running Nerves.Runtime.validate_firmware() when the application starts.

Our existing users will also need to run the firmware validation before upgrading.

Excerpt from the release announcement:

Each rpi* system now does a simple firmware validation check before loading the rootfs. [...] This change requires the firmware to be marked as valid at runtime.

Can I update existing devices?
Nerves rpi* systems < v2.0.0 don’t have this UBoot variable set, so any attempt to update via fwup (such as SSH or upload.sh script) will fail [...] so before updating, you’ll need to manually validate the running firmware with:
Nerves.Runtime.validate_firmware()

https://elixirforum.com/t/nerves-raspberry-pi-systems-v2-0-0-release-candidates/33446

Animation Config Refactor

We need a second pass at animation configuration:

  • Make it so use Animation is all you need and can use the field macros directly.
  • Clean up the DSL macros so they work right (i.e. so you can use things like module attributes when using them)
  • Somehow have definable documentation per field that the live-view UI can use

UI: System page - Backup/restore

We would like to include backup & restore functionality so that a user can save their settings off of the device for safe keeping, and later restore their settings if the device becomes misconfigured.

One option we discussed is to save all of the settings files in a specific directory, then zip/overwrite that entire directory on backup/restore.

Acceptance Criteria

Backup

  • The settings page (/settings) provides a button to backup the configuration.
  • The backup process allows the user to download a single file (like a zip archive) to their computer.

Restore

  • The settings page provides a button to restore the configuration.
  • The restore process prompts the user for a singe file to restore the configuration from, which is uploaded from their computer to the device.

Design

https://www.figma.com/file/RMYWHeXJoDErWii1jm8C7k/Xebow?node-id=45%3A44

System2

Run on host for development

Xebow should be able to start up the BEAM on the host, without being dependent on running on the target hardware. This will help with working on the web interface, designing animations, and being able to run commands like iex -S mix to experiment with the code without flashing the hardware.

UI: Main page

We would like to redesign the main page of the Xebow Studio UI.

Notes

  • The design is available in Figma for margins, colors, fonts, etc.
  • The following components were inspired by tailwindcss, which can be included as a dependency. (fomantic-ui is another option if we want more pre-built components.)
  • Icons are from the fontawesome free set.
  • We need to try to load assets from the hardware rather than from the web, as the user may not have an internet connection when using the device. If this is not possible, reasonable alternatives should be used when the user is offline.
  • The speedometer icon is intended to link to the telemetry dashboard at /telemetry. This should open in a new tab, as the page does not contain a way to navigate back to Xebow Studio.
  • The hamburger icon is intended for menu items, like device settings, which might not exist in the first iteration. This is ok and the icon can be omitted.
  • The design does not need to be pixel-perfect if another implementation looks better.

Design

Main

UI: Main page - Select animation

We would like to replace the UI functionality of cycling to the next/previous animation with a dropdown menu that allows the user to pick the specific animation they want to play from a list.

Acceptance Criteria

  • The animation dropdown shows the name of the currently playing animation as its current value.
  • The animation dropdown shows a list of active animations (configured from the Animations page) in the dropdown options list.
  • Selecting a dropdown option starts playing that animation.

Design

https://www.figma.com/file/RMYWHeXJoDErWii1jm8C7k/Xebow?node-id=1%3A3

Main

Configure USB gadget device before BEAM boot

We would like to configure the USB gadget device before the BEAM boots so that in the future we can have access to it from a separate application that can send simple HID keyboard reports, like pressing a key to get into the host's BIOS. Due to this we also need to migrate off of usb_gadget since we won't have access to Elixir at this stage.

UI: Use field `doc` information to render configuration

With the use Animation refactor, we can look at making the UI render the description and name using the metadata provided by the doc option given in field definitions.

Because doc is optional, we should keep our current method as a fallback for when no name is provided.

Take care of Phoenix asset setup as part of `mix firmware` task

When building the firmware, the Phoenix assets need to first be fetched, installed, and deployed. While this is easy enough, mix firmware doesn't check or know when the Phoenix assets are missing, and it displays no errors or warnings, so the Live View fails to work correctly.

We should make the mix firmware (and mix firmware.burn) task ask if a user wants to install the Phoenix deps, similar to how mix phx.new does.

Phoenix does it like this: https://github.com/phoenixframework/phoenix/blob/1f0040a513c25a0ffee78931357fde44ac5d0583/installer/lib/mix/tasks/phx.new.ex#L150

Xebow might not need to be this involved. It would be really cool if we could make it more automagic and somehow detect whether the Phoenix assets need to be installed, but it's probably not strictly necessary.

Bare minimum would be a couple sentences in the readme about how to do this.

UI: Animations page

We would like to expose each of the animation types on a page where the user can toggle each one on or off. This will include or exclude the respective animation in the list of animations that can be selected (cycled through) on the dashboard.

This is the first iteration of this design and will be expanded on in the future.

Acceptance Criteria

  • A page at /animations displays the animation types.
  • Each animation type can be toggled on or off, which makes it either available or unavailable when the user cycles animations.
    • This works when cycling animations on the dashboard page.
    • This works when cycling animations with the hardware keypad.
  • A menu item exists to navigate to the animations page.

Design

https://www.figma.com/file/RMYWHeXJoDErWii1jm8C7k/Xebow?node-id=41%3A0

Settings_ Animations

image

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.