Code Monkey home page Code Monkey logo

anthem-qml's People

Contributors

grejppi avatar jamboxboom avatar secondflight avatar

Stargazers

 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  avatar

anthem-qml's Issues

MainPresenter: SwitchActiveProject must be manually run after CloseProject sometimes

As a general rule, SwitchActiveProject must be called whenever the active project ought to have changed. This may be confusing when writing UI code. The presenter should take care of this in CloseProject.

This and all related issues should be fixed if the presenter can be made to always figure out what extra steps need to be taken past the actual actions in NewProject and CloseProject.

TabGroup should be more declarative

Tab group manipulation is mostly procedural and manipulates the QML structure directly. QML contains declarative mechanisms to render lists, and using them will simplify the code and make it more idiomatic.

Improve tab change flow

Related to #48.

When a tab is changed in Anthem, the component that renders the tabs sends a message to the presenter asking it to change the tab. It then emits an event for every existing control or data view in the UI. (!!) This design will lead to a high level of complexity and a lot of unnecessary knowledge of UI implementation details by the presenter.

This can be fixed by instead raising a tab change event in the UI and having controls respond to that event by requesting data from the presenter. This leaves the UI code entirely in the UI and will lead to a system that is much more maintainable.

Implement the command pattern in Anthem

There's no way around it: the way Anthem generates and applies its patches for undo and redo is beyond bad. It is cumbersome, highly error-prone, and seems to take the majority of my time when I'm working with data. This must be redesigned. I'm looking at the Command pattern right now - it groups the logic in with the data that describes the logic (the patches). This means the logic for applying the patch and the logic for running the patch in the first place, currently both a web of events and data flow across multiple growing component networks, can be put all in one place, while also doing it all only once.

Perhaps this should have been an obvious solution, or at least one I should have found before now. My lack of experience is no excuse to have not consulted basic design patterns before attempting a naive undo/redo implementation. Better now than later though!

The in-memory JSON model is unnecessary and should be removed

The current architecture uses two in-memory representations of data, one in C++ and one in JSON. Both are mutated regularly by user actions. The C++ model does not perform serialization; Anthem instead relies on the in-memory JSON representation, stored using rapidjson, for project saving (and soon other tasks as well).

There is a problem here: having two separate data stores means that we must always keep them synced with each other. Any error in properly syncing these will go undetected until the user saves and loads the project, at which point they will load (from JSON, into both the JSON model and C++ model) something different from what they thought they saved (as shown to them from the C++ model).

There's an obvious solution: just remove the JSON model and add serialization to the C++. This will have the added benefit of removing runtime overhead and code clutter.

There is one caveat: with no JSON model, it will be impossible to verify that generated JSON patches are being applied correctly. This can (and should) be easily fixed by adding extra debugging functionality to the engine class to track what the JSON should be as described by the patches generated by the C++. I think I'll have this optionally enabled with a command line flag.

Doesn't run

Hi, I've been trying this software today. It does look to compile fine (I didn't see anything wrong while doing so), but it doesn't run when launched from the terminal. The error message is:

QQmlApplicationEngine failed to load component
qrc:/main.qml:80 Expected token `numeric literal'
qrc:/main.qml:80 Unexpected token `>'
qrc:/main.qml:81 Expected token `:'
qrc:/main.qml:81 Expected token `}'

PS: Debian buster up-to-date here

Main window does not have a minimum width or height

The solution for this is not trivial. For example, the SplitView will only resize the "fill remaining" item, so in some cases resizing the window will cause an invalid UI state, where in other cases it won't. Fixing this may involve factoring out SplitView in some cases.

Dragging the window in circles sometimes causes it glitch out and fly off screen

This happens most easily in debug mode, though you can see some hints that it's not quite behaving right in release. I think the responsiveness of the render loop may have something to do with whether it spirals out of control or not.

Below are the errors generated when this happens. Notice how near the bottom the geometry values seem to be in a feedback loop, getting bigger in magnitude and jumping from positive to negative.

QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=826,2411 1300x768) with invalid geometry: QRect(826,2411 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=381,-996 1300x768) with invalid geometry: QRect(381,-996 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=1305,5204 1300x768) with invalid geometry: QRect(1305,5204 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=166,1983 1300x768) with invalid geometry: QRect(166,1983 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=187,1971 1300x768) with invalid geometry: QRect(187,1971 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=654,1978 1300x768) with invalid geometry: QRect(654,1978 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=654,1975 1300x768) with invalid geometry: QRect(654,1975 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=654,1967 1300x768) with invalid geometry: QRect(654,1967 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=656,1962 1300x768) with invalid geometry: QRect(656,1962 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=619,1984 1300x768) with invalid geometry: QRect(619,1984 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=528,1975 1300x768) with invalid geometry: QRect(528,1975 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=932,1964 1300x768) with invalid geometry: QRect(932,1964 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-985,1979 1300x768) with invalid geometry: QRect(-985,1979 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1016,1965 1300x768) with invalid geometry: QRect(-1016,1965 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-937,1978 1300x768) with invalid geometry: QRect(-937,1978 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-401,1980 1300x768) with invalid geometry: QRect(-401,1980 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1149,1977 1300x768) with invalid geometry: QRect(-1149,1977 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1291,1978 1300x768) with invalid geometry: QRect(-1291,1978 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1291,1963 1300x768) with invalid geometry: QRect(-1291,1963 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1278,1981 1300x768) with invalid geometry: QRect(-1278,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1262,1981 1300x768) with invalid geometry: QRect(-1262,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1232,1981 1300x768) with invalid geometry: QRect(-1232,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-1009,1981 1300x768) with invalid geometry: QRect(-1009,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-958,1981 1300x768) with invalid geometry: QRect(-958,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-865,1978 1300x768) with invalid geometry: QRect(-865,1978 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-149,1971 1300x768) with invalid geometry: QRect(-149,1971 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-149,1971 1300x768) with invalid geometry: QRect(-149,1971 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=71,1991 1300x768) with invalid geometry: QRect(71,1991 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=14,1981 1300x768) with invalid geometry: QRect(14,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=14,1980 1300x768) with invalid geometry: QRect(14,1980 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=10,1976 1300x768) with invalid geometry: QRect(10,1976 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-39,1967 1300x768) with invalid geometry: QRect(-39,1967 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-39,1966 1300x768) with invalid geometry: QRect(-39,1966 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-38,1981 1300x768) with invalid geometry: QRect(-38,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-31,1981 1300x768) with invalid geometry: QRect(-31,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-8,1981 1300x768) with invalid geometry: QRect(-8,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=5,1981 1300x768) with invalid geometry: QRect(5,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=15,1981 1300x768) with invalid geometry: QRect(15,1981 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-550,1977 1300x768) with invalid geometry: QRect(-550,1977 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-593,1974 1300x768) with invalid geometry: QRect(-593,1974 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=637,1980 1300x768) with invalid geometry: QRect(637,1980 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=633,1978 1300x768) with invalid geometry: QRect(633,1978 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=2462,2294 1300x768) with invalid geometry: QRect(2462,2294 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=2462,2294 1300x768) with invalid geometry: QRect(2462,2294 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-6437,-3968 1300x768) with invalid geometry: QRect(-6437,-3968 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=26906,20174 1300x768) with invalid geometry: QRect(26906,20174 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)
QSGThreadedRenderLoop: expose event received for window QQuickWindowQmlImpl_QML_135(0x4eca9c70 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window|FramelessWindowHint), geometry=-25760,-19844 1300x768) with invalid geometry: QRect(-25760,-19844 1300x768) on QScreen(0x1fc2e0, name=\\.\DISPLAY1)

List of unfinished UI components

Below is a list of atomic UI components that are either partially complete or not yet started. They are in no particular order.

  • Scrollbars
  • Knobs
  • Sliders
  • Accordion list (sidebar)
  • Color picker (no mockup exists yet) (#45)
  • Piano control
  • Right click menu (#41)
  • Button groups (#22)

There are a lot that are not listed here, but most are part of a bigger system and ought to be built in that context.

Reimplementation of what() in the InvalidProjectException has undefined behavior

From Dom:

_message.toUtf8() returns a QByteArray. QByteArray defines operator const char *, which is used to return its internal buffer from what. But at the end of the return statement, the QByteArray is destructed, taking its internal buffer with it.
Thus anything reading from the return value of what is reading deleted memory, which is undefined behaviour.
Undefined behaviour includes, among other things, "actually doing what you want it to", which seems to be what is happening in the release build case.
You could try storing a QByteArray in the exception instead, and use QString::toUtf8 in the constructor rather than in what. That way the buffer lives as long as your exception does.

Investigate UI tweaks for menus

Menus may benefit from some minor adjustments and improvements. The following ideas will be evaluated, and implemented if they feel right:

  • Padding at the top and bottom of menus
  • Slight spacing between menus and their parent/origin
  • Less rounding on corners
  • Fly in animation

This may make it possible to remove a large amount of duplicated code due to the specifics of the rounded corner implementation with opacity masks.

More items will be added as I think of them.

Investigate adding one or more state + logic + communication layers in QML

The Anthem UI tries to separate the UI + display logic from the data manipulation and app logic, but it's not doing a very good job right now. A lot of transient UI state is flowing into the presenter, partly due to some emergent design (not the good kind) during development.

A logic node will be added at the root of the QML tree, and another will be added above the pattern editor. These will handle UI state, and all data will flow through them, further separating functionality into preset categories and hopefully reducing a lot of future technical debt before it happens.

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.